static int TICK_MSG = 1;
static long TICK_TIME = 1000;  / 1 second

class MyHandler extends Handler {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case TICK_MSG:
                sendMessageDelayed(obtainMessage(TICK_MSG), TICK_TIME);
                onTick();
            default:
                super.handleMessage();
    }
}

MyHandler mHandler = new MyHandler();

void onTick() {
    // Do something
}

void startTicking() {
    mHandler.removeMessages(TICK_MSG);
    mHandler.sendEmptyMessage(TICK_MSG);
}

void stopTicking() {
    mHandler.removeMessages(TICK_MSG);
}


That is a very easy way to implement timed events without using threads.  If
your onTick() method is blocking, then you'll need to think about how to
introduce threading.  Exactly how you do this will depend on your needs, but
it does make things a lot more complicated just by the nature of there being
multi-threading involved.  (For example, the startTicking/stopSticking
implementations become more complicated if you can't assume atomicity due to
everything being on one thread.)

On Wed, Apr 20, 2011 at 10:34 AM, Indicator Veritatis <[email protected]>wrote:

> Dianne-
>
> I expect your suggestion is sound, since you do know Android so well,
> and in particular, what Handlers are good for and how to use them. I
> also expect that the reason Diego did not use a Handler was that he
> could easily find copious documentation on how to use a "raw thread",
> but nothing comparable on how to use a Handler; he almost got the
> synchronization idiom right: the !wifiSearchComplete test needs to be
> repeated inside the synchronized block or moved inside entirely
> (http://download.oracle.com/javase/tutorial/essential/concurrency/
> guardmeth.html).
>
> Since he almost got it right, he seems to have tolerably good grasp of
> Java objects and methods Thread, locks, wait(), notify() and the
> synchronized keyword. But to implement the HandlerThread technique, he
> has to learn several new objects: Handler, HandlerThread, Message,
> Looper, MessageQueue.
>
> The http://developer.android.com/reference/android/os/Handler.html
> link certainly leaves much to be desired. Badly written sentences like
> "When you create a new Handler, it is bound to the thread / message
> queue of the thread that is creating it -- from that point on, it will
> deliver messages and runnables to that message queue and execute them
> as they come out of the message queue." leave the reader doubting it
> is worth the bother, especially if the reader has no good sample code
> in front of him.
>
> What is so wrong with that sentence? 1) pronoun reference for 'it' is
> way too vague: does 'it' stand for 'Handler' or for thread, or the
> message queue? After some reflection it appears that 'Handler' has to
> be the right answer, but then 2) what get executed "as they come ouf
> of the message queue"? It would appear to mean that both messages and
> runnables get executed, but what it means to execute a message is far
> from clear. It is a type mismatch: one executes runnables but handles
> messages. Not to mention, 3) it says, "to be executed in the future",
> but it is far from clear which method does this execution.
>
> Also, the purpose of Handlers is described as being mainly either one
> of two things: either 1) scheduling for the future, or 2) executing on
> a different thread. Which is Diego doing? Apparently not 2), since you
> said "if the code is not doing blocking". But 1) isn't quite right
> either, since he wants to execute the scan again after
> WIFI_SCAN_TIMEOUT only if the previously initiated scan does NOT
> complete. Of course, he could schedule and unschedule as needed, but
> this looks like it could turn out to be more complicated than
> debugging the 'raw thread' code.
>
> Of course, I can't guarantee that the one change I suggest will fix
> his problem, since I have not run it; I have not run it, because I am
> not seeing code for the Service.
>
> Even more "of course", it is quite possible that a pointer to sample
> code that does the kind of timing he needs, without excess baggage,
> showing how to use handleMessage() and hasMessages() to do timing by
> responding to the delayed message (and where to place them to avoid
> ANR -- his timeouts are 15S and 60S), could tip the balance in favor
> of using Handler.
>
> On Apr 18, 4:22 pm, Dianne Hackborn <[email protected]> wrote:
> > I suggest not using a raw thread.  If you need it on a separate thread,
> use
> > a HandlerThread and Handler.sendMessageDelayed() to do your timing.
> >
> > Even better -- if the code is not doing blocking operations, there is no
> > need for another thread at all; just make a class with a Handler in it
> and
> > use Handler.sendMessageDelayed() to schedule your work on the main
> thread.
> >
> > On Mon, Apr 18, 2011 at 3:58 PM, Diego Tori
> > <[email protected]>wrote:
> >
> > > So yeah, I managed to try calling the wifi scanner in this fashion
> within
> > > my thread:
> > >         private Object _lock = new Object();
> >
> > >         private final long SLEEP_TIME = 15000; //Scan every 15 secs
> > >         private final long WIFI_SCAN_TIMEOUT = 60000; //One minute
> timeout
> > > for getting called back, otherwise, initiate a new scan.
> >
> > >        @Override
> > >         public void run() {
> > >             while(running){
> > >                 //Start a new scan;
> > >                 wifiSearchComplete = false;
> > >                 _wifiMan.startScan();
> > >                 while(!wifiSearchComplete){
> > >                     synchronized(_lock){
> > >                         try{
> > >                             _lock.wait(WIFI_SCAN_TIMEOUT);
> > >                         } catch (InterruptedException ie){
> > >                              Log.d(TAG, TAG+".run() caught " +
> > > ie.getMessage() +" when trying to sleep for " +
> (WIFI_SCAN_TIMEOUT/1000)
> > > +"secs.");
> > >                              Thread.currentThread().interrupt();
> > >                         }
> > >                     }
> > >                     if(!wifiSearchComplete){
> > >                         synchronized(_lock){
> > >                             //Try scanning again since we didn't get
> called
> > > back at all;
> > >                             _lock.notify();
> > >                         }
> > >                     }
> > >                 }
> > >             }
> > >         }
> >
> > >         public boolean isRunning(){
> > >             return running;
> > >         }
> >
> > >         public void stop(){
> > >             synchronized(_lock){
> > >                 running = false;
> > > //unregister receivers and cleanup
> > >                 _lock.notify();
> >
> > >             }
> > >         }
> >
> > >         @Override
> > >         public void onReceive(Context context, Intent intent) {
> > >             synchronized(_lock){
> > >                    wifiSearchComplete = true;
> > >                    //iterate through our SSID's
> > >                     try{
> > >                         _lock.wait(SLEEP_TIME);
> > >                     } catch (InterruptedException ie){
> > >                          Log.d(TAG, TAG+".onReceive() caught " +
> > > ie.getMessage() +" when trying to sleep for " + (SLEEP_TIME/1000)
> +"secs.");
> > >                          Thread.currentThread().interrupt();
> > >                     }
> > >                     _lock.notify();
> > >                 }
> > >         }
> >
> > > However, even though it waits every 15 seconds before it scans again,
> when
> > > trying to exit my test activity (calling onDestroy) it blocks the main
> > > thread for the sleep time, before it unbinds the service. In other
> words, is
> > > this the appropriate way of trying to accomplish what I want to do w/o
> > > blocking, or do I have to simply create a BroadcastReceiver and call
> > > Thread.sleep at the end of onReceive before calling starting a new
> scan?
> >
> > >  --
> > > 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
> >
> > --
> > Dianne Hackborn
> > Android framework engineer
> > [email protected]
> >
> > Note: please don't send private questions to me, as I don't have time to
> > provide private support, and so won't reply to such e-mails.  All such
> > questions should be posted on public forums, where I and others can see
> and
> > answer them.
>
> --
> 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
>



-- 
Dianne Hackborn
Android framework engineer
[email protected]

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.

-- 
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

Reply via email to