views:

230

answers:

2

Hello!

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

A: 

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

CommonsWare
I just found that this very code works when run as an application in OS, but fails when running as a test... So I guess this is something else missing. maybe related to activity...
dpimka
A: 

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.

Dave Webb
I thought so to, but the Looper is created indeed. Because when I try to create it by myself (including trying your suggestion above) I get:"java.lang.RuntimeException: Only one Looper may be created per thread"Also I just found that the code (unchanged) works fine when ran inside a full blown app in OS. On the other hand, when I run it as a test case it fails to work...Any hints?Looper is ok, it is not null, no exceptions, no errors in log. I'm puzzled.
dpimka