如何在服务中显示工作线程的吐司?

时间:2014-08-17 17:03:21

标签: android multithreading

我正在使用 AlarmManager 来唤醒设备并运行一些任务。这些是在 IntentService 中完成的,因此在与主要线程分开的线程上完成。工作完成后,我想表示祝酒。但是,我收到了这个日志警告,并且没有显示toast:

W/MessageQueue﹕ Handler (android.os.Handler) {b12716d0} sending message to a Handler on a dead thread
    java.lang.RuntimeException: Handler (android.os.Handler) {b12716d0} sending message to a Handler on a dead thread
            at android.os.MessageQueue.enqueueMessage(MessageQueue.java:320)
            at android.os.Handler.enqueueMessage(Handler.java:626)
            at android.os.Handler.sendMessageAtTime(Handler.java:595)
            at android.os.Handler.sendMessageDelayed(Handler.java:566)
            at android.os.Handler.post(Handler.java:326)
            at android.widget.Toast$TN.hide(Toast.java:370)
            at android.app.ITransientNotification$Stub.onTransact(ITransientNotification.java:55)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)

我知道关于这个话题还有其他一些问题,但我已经尝试了所有的建议,但都没有。我正在使用:

Handler handler = new Handler();
handler.post(new Runnable()
{
    @Override
        public void run()
            {
                Toast.makeText(context, R.string.toast, Toast.LENGTH_LONG).show();
            }
});

我也试过了:

Handler handler = new Handler(Looper.getMainLooper());

我仍然收到警告,没有敬酒。

从我的 IntentService 显示此吐司的方式是什么?

提前致谢!

1 个答案:

答案 0 :(得分:4)

首先,你真的不应该发送Toast消息来自服务或很久以前用户没有发起的任何任务。否则,用户不知道Toast的来源;她甚至无法确定它来自哪个应用程序 - 一般来说绝对令人困惑和糟糕的做法。

但要回答您的问题,当您使用new Handler()创建处理程序时,它会附加到创建它的线程上。因此,如果您想从服务(来自任何线程)向UI /主线程发布内容,那么您应该在例如onCreate()方法中创建Handler;因为onCreate(),通常是任何Android回调方法,都是在UI线程上调用的。所以:

public class MyService extends Service {

    private Handler mMainThreadHandler;

    @Override
    public void onCreate() {
        mMainThreadHandler = new Handler();
    }

    [...]
}

或者,您想创建一个附加到UI线程的Handler并且不想关心它的创建位置,然后使用new Handler(Looper.getMainLooper())。这样它就连接在主弯针上;这是主线程的重量级。

public class MyService extends Service {

    private Handler mMainThreadHandler = new Handler(Looper.getMainLooper());

    [...]
}

我知道你写过你试过了;但它应该有用。

虽然,我建议你不要打扰处理程序;请改用针。 Needle是一款简单而强大的Android多线程库。有了它,你可以这样说:

Needle.onMainThread().execute(new Runnable() {
    @Override
    public void run() {
        // e.g. change one of the views
    }
});

在GitHub上查看:https://github.com/ZsoltSafrany/needle