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

Reply via email to