Yep, that looks good.
Strictly, it is not necessary to do the 'if (...)' statement at all. You
can just always do the mHandler.post(...) instead.
On Tuesday, October 30, 2012 2:39:24 PM UTC-4, Jay Howard wrote:
>
> Here's what I ended up doing:
>
> 1. Ensure that my timer class, which creates a Handler in its <init>
> method on the caller's thread, is always instantiated on the main thread.
> 2. My class is also a BroadcastReceiver, but onReceive() is guaranteed to
> be called by the main thread so it can access the handler directly.
> 2. Structure each external method that accesses the handler (and that
> could potentially be called from multiple threads) as follows:
>
> private void doSomethingWithHandlerSync() {
> // access the handler directly
> }
>
> public void doSomethingWithHandler() {
> if (Thread.currentThread().equals(mHandler.getLooper().getThread())) {
> doSomethingWithHandlerSync();
> } else {
> mHandler.post(new Runnable() {
> @Override
> public void run() {
> doSomethingWithHandlerSync();
> }
> });
> }
> }
>
> Does that thread check look right? Seems like it should be sufficient to
> guarantee that doSomethingWithHandlerSync(), handleMessage() and
> onReceive() will never execute concurrently.
>
>
> On Tue, Oct 30, 2012 at 10:09 AM, Jay Howard
> <[email protected]<javascript:>
> > wrote:
>
>> Thanks so much for the response! If you'll indulge me with a few more
>> questions...
>>
>> So I instantiate the handler in the onCreate() method of my Application,
>> which I assume means it's tied to the UI thread.
>>
>> The method that removes and re-sends messages is called primarily on the
>> UI thread, but can also be called from an IntentService that I use to
>> handle network communication. Since the service is executed by a thread
>> other than the UI thread it appears that I do need to synchronize.
>>
>> To give some more detail on my goals for this: I'm attempting to use the
>> handler to track both user inactivity and server session expiration. The
>> Service calls a "session refreshed" method to remove session-related
>> delayed messages and re-add them with a new delay. The UI thread calls an
>> "user activity occurred" method to indicate the user "did something"; that
>> method removes inactivity-related delayed messages and re-adds them with a
>> new delay.
>>
>> One other kink: I also have code to respond to SCREEN_ON and
>> SCREEN_OFF. At screen off I remove all messages from the handler; at
>> screen on I re-send each message that was queued at the point at which
>> screen off occurred, albeit with a revised delay to account for the time
>> that elapsed while the screen was off.
>>
>>
>>
>> On Tue, Oct 30, 2012 at 9:43 AM, Streets Of Boston
>> <[email protected]<javascript:>
>> > wrote:
>>
>>> It depends which thread is callling the code-snippet you show above (the
>>> one calling 'removeMessage').
>>>
>>> If your code, calling 'removeMessage', is run on the same thread that is
>>> tied to the *handler*, you're fine. The message you sent will not be
>>> handled/run until your code finishes first. No extra work necessary.
>>>
>>> If your code, calling 'removeMessage' is run on another thread than the
>>> one tied to the *handler*, you need to sync it up. This could be as
>>> simple as send another message on that handler that will call
>>> 'removeMessage': E.g.:
>>> handler.post(new Runnable() {
>>> public void run() {
>>> // Right now, calling 'removeMessages', etc. is done
>>> // on the handler's thread as well.
>>> handler.removeMessages(MSG_**ONE);
>>> handler.removeMessages(MSG_**TWO);
>>> ...
>>>
>>> if (conditionOne)
>>> handler.**sendEmptyMessageDelayed(MSG_**ONE, timeoutOne);
>>>
>>> if (conditionTwo)
>>> handler.**sendEmptyMessageDelayed(MSG_**TWO, timeoutTwo);
>>> }
>>> });
>>>
>>> Since both the 'removeMessages' and 'sendEmptyMessageDelayed' are called
>>> on 'handler' the Runnable needs to finish first before any other message
>>> sent to 'handler' can be executed.
>>>
>>>
>>> On Tuesday, October 30, 2012 9:17:39 AM UTC-4, Jay Howard wrote:
>>>>
>>>> I'm using a timer to manage timeout events, and would like to ensure
>>>> that a particular method runs atomically without the handler issuing
>>>> messages while the method is executing. Its basic form is:
>>>>
>>>> handler.removeMessages(MSG_**ONE);
>>>> handler.removeMessages(MSG_**TWO);
>>>> ...
>>>>
>>>> if (conditionOne)
>>>> handler.**sendEmptyMessageDelayed(MSG_**ONE, timeoutOne);
>>>>
>>>> if (conditionTwo)
>>>> handler.**sendEmptyMessageDelayed(MSG_**TWO, timeoutTwo);
>>>>
>>>> ...
>>>>
>>>> What I want to avoid is a situation where, before the removeMessages()
>>>> calls execute, one of the messages reaches its timeout and is delivered to
>>>> the message queue, then I send a duplicate one immediately after. My goal
>>>> is to guarantee that there is never more than one of each message type "in
>>>> flight" on the handler at any given time.
>>>>
>>>> Does the Handler class synchronize on MessageQueue when delivering its
>>>> messages? If so, then could I just synchronize on the MessageQueue? Or
>>>> would that be a terrible idea, since it's used by entities other than just
>>>> my Handler?
>>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Android Developers" group.
>>> To post to this group, send email to
>>> [email protected]<javascript:>
>>> To unsubscribe from this group, send email to
>>>
>>> For more options, visit this group at
>>> http://groups.google.com/group/android-developers?hl=en
>>>
>>
>>
>
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en