2

I have an class extends HandlerThread, it looks like this:

public class MyHandlerThread extends HandlerThread {

  private Object lock;

  //constructor
  public MyHandlerThread() {
     super(“MyHandlerThread”);
     lock = new Object();
  }

  public void prepare() {
     //starts the handler thread
     start();

     //Wait for thread starting
     Log.d(TAG, "wait for thread starting…");
     synchronized (lock) {
        try {
            lock.wait(5000);
        } catch (InterruptedException e) {
            Log.e(TAG, "Failed to wait for thread to start");
        }
     }

     //WHY getLooper() returns null here?
     if(getLooper() == null) {
         Log.d("GET LOOPER NULL!");
     }
  }

  @Override
  public void run() {
    Log.d("run() begin...");
    initializeSomeObjects()
    Log.d(“initialise objects done!”);

    //Notify that run() finished
    synchronized (lock) {
       lock.notify();
    }
    Log.d("run() end!”);
  }

}

As you see above, the prepare() function starts the thread & wait for run() to be finished, then try to get looper.

In another class, I create an instance of MyHandlerThread & start it:

MyHandlerThread myThread = new MyHandlerThread();
myThread.prepare();

Logs showing in console:

wait for thread starting…
run() begin...
initialise objects done!
run() end!
GET LOOPER NULL!

Why in prepare() function, call to getLooper() returns null though the thread is already started (run() is executed)?

user842225
  • 5,445
  • 15
  • 69
  • 119
  • 1) create a new `HandlerThread`: `HandlerThread ht = new HandlerThread("foo");` 2) start it 3) make a `Handler`: `Handler h = new Handler(ht.getLooper()) {...` 4) send `Message`s: `h.sendEmptyMessage(999)` – pskink Oct 08 '15 at 16:12
  • Thanks, I found the same thing in google, but why with my approach `getLooper()` is NULL? My code looks like doing the same steps, only difference is I start the thread inside the class. – user842225 Oct 08 '15 at 16:15
  • there are really 3 steps to make `Handler` / `HandlerThread` ready and one to set `Message`s... why make it harder? why do you want to extend `HandlerThread` ? – pskink Oct 08 '15 at 16:17
  • I really want to know the reason behind. It is a way to understand what is happening underneath, isn't it? Simply get it work is not my point, that's why I say I found your suggestion with google as well. – user842225 Oct 08 '15 at 16:18
  • so if you want to know what is underneath then look [here](http://androidxref.com/6.0.0_r1/xref/frameworks/base/core/java/android/os/HandlerThread.java) – pskink Oct 08 '15 at 16:20
  • and here is my answer for a similar question: http://stackoverflow.com/a/25096981/2252830 – pskink Oct 08 '15 at 16:22
  • btw if yiu only want to do some action (`initializeSomeObjects`) in a calling thread do it in `prepare` before starting the `HandlerThread` and if you want to do that in background thread simply override `onLooperPrepared` which is called right before `Looper.loop()` is called – pskink Oct 09 '15 at 10:50

1 Answers1

4

HandlerThread Looper is initialized in HandlerThread#run().

If you override the method and don't call super.run(), the init code from superclass is not executed.

laalto
  • 150,114
  • 66
  • 286
  • 303
  • 1
    not really: `getLooper()` method returns a `Looper` that is associated with this `HandlerThread`, btw he is calling it from a UI thread and UI thread does have a `Looper`, doesn't if? – pskink Oct 08 '15 at 19:51
  • @pskink Thanks, overlooked the fact that it was `HandlerThread#getLooper()` and not e.g. `Looper#myLooper()`. Answer rewritten. – laalto Oct 09 '15 at 04:42