3

In one of my onTouch() listeners, I currently check for boolean user setting before deciding how to handle the touch event:

boolean shouldCue = preferences.getBoolean(v.getContext().getString(R.string.should_cue), true);

Observing LogCat, I can see that when the user touches the screen, this statement is called numerous times!

So, I was thinking of "caching" that shouldCue boolean by implementing an onSharedPreferenceChanged() listener.

I could of course go ahead and implement this and... observe negligible difference on my super-fast Android device. I can't possibly test this on "the majority of Android devices" out there because there are way too many variations.

So my questions are:

  1. Would onSharedPreferenceChanged() be called even if the preference wasn't changed via UI? (i.e. programmatically via editor.commit();)
  2. Provided that SharedPreferences boolean can be modified from either UI or programmatically (but not both simultaneously), would caching it mandate @Synchronized handling?
  3. Any estimates regarding the performance difference between the cached vs. non-cached method? (to simplify the question, let's assume we are referring to an old phone like the Droid 1 A855)
Community
  • 1
  • 1
ateiob
  • 9,016
  • 10
  • 44
  • 55
  • 4
    Do you not think a better solution would be to investigate why it is being called numerous times? – jiduvah Jun 19 '12 at 15:59
  • @jiduvah It's being called numerous times because that's how `onTouch()` works: On a simple up/down, there are only a few such calls. But if user moves finger... you'll see tons of them. That's OK. That's how it should be. The idea is to spend minimal time at the listener. By design. – ateiob Jun 19 '12 at 16:07
  • 1
    Why are you using onTouch instead of on click? Surely if the listener is firing so fast there is actually no way the user could know what he is pressing? – jiduvah Jun 19 '12 at 16:15
  • @jiduvah Why does onTouch() exist then? Can onClick() do everything onTouch() can? – ateiob Jun 19 '12 at 16:24
  • 1
    I have never used it but I would guess onTouch() would be used for when you need more control over user touches. It sounds like you only need an onClick() event. I have never had the problem you are facing with onClick(). No it can't do everything onTouch() can do but it sounds like it would be more suited to your needs – jiduvah Jun 19 '12 at 16:32
  • @jiduvah onTouch() can block an event from further traveling up the view chain (by returning `true`). onClick() can't. It only responds to clicks. I need to stick with onTouch(). – ateiob Jun 19 '12 at 16:34
  • the docs say that it returns true when it has consumed the motion event. Are you tracking motion? – jiduvah Jun 19 '12 at 16:42
  • @jiduvah Please don't divert from the original subject. Let's just assume I must use onTouch(). Can you answer any of the 3 questions above? – ateiob Jun 19 '12 at 16:44
  • 1
    I am not diverting, I am trying to consider the scope of your problem – jiduvah Jun 19 '12 at 16:45

1 Answers1

2

In my opinion, it would be best to avoid reading preferences in the onTouch() method: it's fired really fast, and reading from preferences imply parsing xml (which is not exactly something you should do this much times per second). You can try it on the emulator and see if it reacts fast enough but it would be best to read that somewhere else or find another way to store/get this boolean value.

EDIT: Regarding the questions:

1) Yes,and even if the preference wasn't changed at all

2) Yes it can be implemented this way, but this may lead to many issues, especially if you plan to reuse the view

3) I can't estimate exactly the impact since on other device because of many factors (hardware, os version, jit enabled, etc.) but without benchmarking, the cached method seems to be the most efficient.

Do you really have to manipulate that boolean in the onTouch() method ? And in this case, why not defining hooks or listeners ?

m.diallo
  • 56
  • 5
  • +1. In other words, you recommend caching. BTW, I did try it but as I mentioned my Android device is very fast and the performance is acceptable even with reading preferences in the onTouch(). Can you answer one or more of the 3 questions above? – ateiob Jun 19 '12 at 16:47
  • Thanks for addressing the 3 issues. Answering your question: If I cache that boolean (as I was planning), no manipulation (or even preferences reading) would occur in onTouch(). That's the purpose of my entire question. The manipulation will occur in an `onSharedPreferenceChanged()` listener as I mentioned in my OP. – ateiob Jun 19 '12 at 17:20
  • Reporting back: Caching works like a charm. **1.** onSharedPreferenceChanged() is called even when preference programmatically changed via `editor.commit()`. **2.** @Synchronized handling not needed. **3.** Didn't notice significant performance improvement but it's always good to know that I'm using a more correct (elegant?) approach. – ateiob Jun 19 '12 at 17:49
  • 1
    You are welcome :). And for the third point, more readable (maintainable ?) solution I think – m.diallo Jun 19 '12 at 17:53
  • 1
    FYI: The documentation for [onSharedPreferenceChanged()](http://developer.android.com/reference/android/content/SharedPreferences.OnSharedPreferenceChangeListener.html#onSharedPreferenceChanged%28android.content.SharedPreferences,%20java.lang.String%29) states: "*This may be called even if a preference is set to its existing value.*" but in actuality it will only be called if the preference value **actually changed!** (or added/removed). – ateiob Jun 19 '12 at 18:08