如果上下文相同,为什么在Android中制作Toast的位置很重要?

时间:2014-03-05 01:27:02

标签: android toast intentservice

我有一个遗留IntentService尝试使用Toast消息来显示错误消息。 1 我想要显示消息,并添加了代码以使它们在正确的线程。最简单的更改是传入构造的Toast对象,然后在UI线程上显示它。但是,如果我在发布的runnable中制作,则仅显示 Toast,而不是我传入预先制作的Toast

这有效:

@Override
protected void onHandleIntent(Intent intent) {
    showToast("Error", Toast.LENGTH_LONG);
}

private void showToast(final String msg, final int duration) {
    new Handler(getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            // Make and show the toast in the posted runnable
            Toast.makeText(getApplicationContext(), msg, duration).show();
        }
    });
}

不起作用

@Override
protected void onHandleIntent(Intent intent) {
    // Make the toast here
    Toast myToast = Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG);
    showToast(myToast);
}

private void showToast(final Toast toast) {
    new Handler(getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            // Show the toast here
            toast.show();
        }
    });
}

在这两种情况下,上下文都是应用程序上下文,我没有在源代码中看到任何会导致一个版本工作的内容,但另一个版本没有。相反,后者具有相同的问题,就像Toast直接显示在IntentService中一样:“Handler(android.os.Handler){...}在死线程上向Handler发送消息”,Toast没有消失,等等< / p>

为什么Toast必须在主线程上制作,而不仅仅是显示

1。遗产=我不认为在Toasts中显示错误消息是很棒的UI,我不认为服务直接向用户显示消息是一个好主意,但这就是我交给的代码,我想把它变成这个小小的好一点。

1 个答案:

答案 0 :(得分:10)

在你发布的第二个代码中,Toast是在后台线程中创建的,后台线程有一个looper和handler设置(这是IntentService的重点)。

toast使用当前线程的looper来创建一个处理程序,但是一旦IntentService完成处理onHandleIntent中的工作,它就会自行停止(如果没有其他意图要处理) - 破坏Toast的处理程序依赖的线程上。

第327行:https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/Toast.java

在runnable中播放toast是有效的,因为此时,当前线程是UI线程。