dimsuz
dimsuz

Reputation: 9207

Handler fails to deliver a message or a Runnable to the main thread

I have an app with a two threads - main and data loader. When data loader finishes it posts a Runnable object to the main thread (as described in the DevGuide), but it never gets delivered and run.

Here's the basic code:

class MyApp extends Application
{
   public void onCreate()
   {
         LoaderThread t = new LoaderThread();
         t.start();
   }

   private class LoaderThread extends Thread
   {
        public void run()
        {
             SystemClock.sleep(2000);
             boolean res = m_handler.post(m_runnable);
             if(res)
                Log.d(TAG, "Posted Runnable");
        }
   }

   private final Handler m_handler = new Handler();
   private final Runnable m_runnable = new Runnable() {
             public void run()
             {
                 Log.d(TAG, "Hey, i'm runnable!");
             }
        }
}

Also it maybe important to note that I ran this code as a unit-test derived from an ApplicationTestCase:

class MyAppTest : public ApplicationTestCase
{
     public MyAppTest()
     {
          super(MyApp.class);
     }

     public void testLoading()
     {
          createApplication();
          // few asserts follow here...
     }
}

So this fails. Runnable never gets run() called, although the log indicates that it has been posted successfully. I also tried to send simple messages instead of posting runnable (m_handler.sendEmptyMessage(1) for example) - they never get delivered to handler's callback in the main thread.

What do I miss here?

Thanks in advance :)

Upvotes: 5

Views: 3893

Answers (3)

ThomasW
ThomasW

Reputation: 17307

An alternative to calling Looper.prepare() is to call new Handler(Looper.getMainLooper()). The problem with calling Looper.prepare() is that it will throw an exception when there is already a looper on your thread. Chances are you are writing code that has to run under different environments and this solution will handle more cases.

See: AsyncTask and Looper.prepare() error

Upvotes: 0

David Webb
David Webb

Reputation: 193686

A Handler requires a Looper in order to work. The Looper provides a message queue required by the Handler.

All instances of Activity have a Looper as one is used to process UI Events, but you can create your instance of Looper elsewhere.

Have a look in your Log output to see if Android is complaining about the absence of a Looper.

If it is, you might be able to fix by add the following to the top of your onCreate() method:

Looper.prepare(); 
m_handler = new Handler();
Looper.run();

And remove the initialisation of m_handler from later in your code.

Upvotes: 1

CommonsWare
CommonsWare

Reputation: 1006614

Handler only works in an Activity AFAIK. You are attempting to use it in an Application.

Upvotes: 0

Related Questions