【问题标题】:Handler fails to deliver a message or a Runnable to the main threadHandler 无法向主线程传递消息或 Runnable
【发布时间】:2011-01-18 09:15:07
【问题描述】:

我有一个带有两个线程的应用程序 - 主线程和数据加载器。当数据加载器完成时,它会将一个 Runnable 对象发布到主线程(如 DevGuide 中所述),但它永远不会被传递和运行。

这是基本代码:

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!");
             }
        }
}

还需要注意的是,我将此代码作为派生自 ApplicationTestCase 的单元测试运行:

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

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

所以这失败了。 Runnable 永远不会被调用 run(),尽管日志表明它已成功发布。 我还尝试发送简单消息而不是发布可运行消息(例如 m_handler.sendEmptyMessage(1))——它们永远不会被传递到主线程中的处理程序回调。

我错过了什么?

提前致谢:)

【问题讨论】:

    标签: android user-interface multithreading


    【解决方案1】:

    Handler 仅适用于Activity AFAIK。您正尝试在 Application 中使用它。

    【讨论】:

    • 我刚刚发现这个代码在操作系统中作为应用程序运行时可以工作,但在作为测试运行时会失败......所以我想这是缺少的其他东西。可能与活动有关...
    【解决方案2】:

    Handler 需要Looper 才能工作。 Looper 提供了Handler 所需的消息队列。

    Activity 的所有实例都有一个 Looper,因为其中一个用于处理 UI 事件,但您可以在其他地方创建您的 Looper 实例。

    查看您的日志输出,看看 Android 是否抱怨缺少 Looper

    如果是这样,您可以通过将以下内容添加到您的 onCreate() 方法的顶部来修复:

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

    并从后面的代码中删除 m_handler 的初始化。

    【讨论】:

    • 我是这么想的,但 Looper 确实是创建的。因为当我尝试自己创建它(包括尝试上面的建议)时,我得到:“java.lang.RuntimeException:每个线程只能创建一个 Looper”而且我刚刚发现代码(未更改)在内部运行时工作正常操作系统中的完整应用程序。另一方面,当我将它作为测试用例运行时,它无法工作......有什么提示吗? Looper 没问题,它不为空,没有异常,日志中没有错误。我很困惑。
    • 感谢您的提示!我的代码不在 Activity 内,因此不在 Looper 内......我试图弄清楚为什么通过处理程序发送的消息仅在调用线程停止时才传递。
    【解决方案3】:

    调用Looper.prepare() 的另一种方法是调用new Handler(Looper.getMainLooper())。调用Looper.prepare() 的问题是当你的线程上已经有一个looper 时它会抛出一个异常。您可能正在编写必须在不同环境下运行的代码,而此解决方案将处理更多情况。

    见: AsyncTask and Looper.prepare() error

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多