title: How to force main thread to wait until Looper will end its work
body: <p>I am using <code>Looper</code> inside a <code>Service</code> on Android app. Usually it is working without any issue. But in some cases (for example very often when I am trying to debug my app) it shows up that there is a race inside the app. <code>Looper</code> is starting, <code>Thread</code> and <code>Handler</code> are creating in the method <code>startMessageThread()</code> which is being invoked at the end of the <code>Service.onCreate()</code> method.</p>
  
  <p>The race is because there are other methods and classes which use this class initialized before <code>Looper.loop();</code>. And in some cases these methods are running before <code>Looper</code> ends. It results in <code>NullPointerException</code>.</p>
  
  <pre><code>public class MyService extends Service {
  
      private Thread thread;
      private Handler handler;
  
      @Override
      public void onCreate() {
          super.onCreate();
          //some code
          startMessageThread();
      }
  
      private void startMessageThread() {
          thread = new Thread() {
  
              @Override
              public void run() { 
                  Looper.prepare();
                  handler = new Handler() {
  
                      @Override
                      public void handleMessage(Message msg) {
                          switch (msg.what) {
                              //message handling
                          }
                      }
                  };
                  MyObject myObject = new MyObject(arg1, arg2);
                  myObject.init();
                  myObject.attr = myAttr;
                  Looper.loop();
              }
          }              
      }
  }
  </code></pre>
  
  <p>If I am right, it is quite similar for this question <a href="https://stackoverflow.com/questions/4838207/how-to-create-a-looper-thread-then-send-it-a-message-immediately">How to create a Looper thread, then send it a message immediately?</a> But I don't want to send any message immediately after creating 'HandlerThread'. Just to force main thread to wait in the end of the <code>onCreate</code> method for the <code>Looper</code> ends.</p>
  
  <p>I have tried with this added at the end of the <code>Service.onCreate</code> method:</p>
  
  <pre><code>synchronized (thread) {
      try {
          if (looperRun) {
              wait();
          }
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  }
  </code></pre>
  
  <p><code>looperRun</code> is of course <code>boolean</code>. I have added <code>looperRun = true;</code> before <code>Looper.loor();</code> method invocation. And this code at the end of the <code>startMessageThread()</code> method.</p>
  
  <pre><code>if (looperRun) {            
      notify();
      looperRun = false;
  }
  </code></pre>
  
  <p>In some cases I have got this exception:</p>
  
  <pre><code>java.lang.RuntimeException: Unable to create service com.myapplication.service.MyService:
  java.lang.IllegalMonitorStateException: object not locked by thread before wait()
      at android.app.ActivityThread.handleCreateService(ActivityThread.java:2582)
      at android.app.ActivityThread.access$1800(ActivityThread.java:135)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:136)
      at android.app.ActivityThread.main(ActivityThread.java:5017)
      at java.lang.reflect.Method.invokeNative(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:515)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
      at dalvik.system.NativeStart.main(Native Method)
  Caused by: java.lang.IllegalMonitorStateException: object not locked by thread before wait()
      at java.lang.Object.wait(Native Method)
      at java.lang.Object.wait(Object.java:364)
      at com.myapplication.service.MyService.onCreate(MyService.java:162)
      at android.app.ActivityThread.handleCreateService(ActivityThread.java:2572)
      at android.app.ActivityThread.access$1800(ActivityThread.java:135)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:136)
      at android.app.ActivityThread.main(ActivityThread.java:5017)
      at java.lang.reflect.Method.invokeNative(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:515)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
      at dalvik.system.NativeStart.main(Native Method)
  </code></pre>
  
  <p><strong>EDIT</strong></p>
  
  <pre><code>protected void startMessageThread() {
      MessageThread messageThread = new MessageThread("messageThread");
      messageThread.start();
      messageHandler = new Handler(messageThread.getLooper()) {
  
          @Override
          public void handleMessage(Message msg) {
              switch (msg.what) {
                  //message handling
              }
          }
      };
  }
  
  private class MessageThread extends HandlerThread {
  
      public MessageThread(String name) {
          super(name);
      }
  
      @Override
      public void run() {
          Looper.prepare();
          MyObject myObject = new MyObject(arg1, arg2);
          myObject.init();
          myObject.attr = myAttr;
          Looper.loop();
      }
  }
  </code></pre>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>I have tried with solution similar to this: <a href="https://stackoverflow.com/questions/4838207/how-to-create-a-looper-thread-then-send-it-a-message-immediately">How to create a Looper thread, then send it a message immediately?</a> My code is below. However my app seems to be frozen after start.</p>
  
  <pre><code>private class BackgroundThread extends HandlerThread {
  
      private Handler handler;
  
      public BackgroundThread(String name) {
          super(name);
      }
  
      @Override
      public void run() {
          Looper.prepare();
          backgroundHandler = new Handler() {
  
              @Override
              public void handleMessage(Message msg) {
                  log.finest("DEAService message:" + msg.what);
                  switch (msg.what) {
                      case MSG_INIT:                            
                          MyObject myObject = new MyObject(arg1, arg2);
                          myObject.init();
                          myObject.attr = myAttr;
                          break;
                      //message handling
                  }
              }
          };
          Looper.loop();
      };
  
      public synchronized void waitUntilReady() {
          handler = new Handler(getMainLooper());
      }
  }
  </code></pre>
  
  <p>I start this <code>HandlerThread</code> in this method as previously:</p>
  
  <pre><code>protected void startBackgroundThread() {
      BackgroundThread backgroundThread = new BackgroundThread("backgroundThread");
      backgroundThread.start();
      backgroundThread.waitUntilReady();
      backgroundHandler.sendEmptyMessage(MSG_INIT);
  }
  </code></pre>
  
  <p>As I mentioned above - app seems to be frozen after start. Nothing happens.</p>