我有一个遗留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,我不认为服务直接向用户显示消息是一个好主意,但这就是我交给的代码,我想把它变成这个小小的好一点。
答案 0 :(得分:10)
在你发布的第二个代码中,Toast是在后台线程中创建的,后台线程有一个looper和handler设置(这是IntentService的重点)。
toast使用当前线程的looper来创建一个处理程序,但是一旦IntentService完成处理onHandleIntent中的工作,它就会自行停止(如果没有其他意图要处理) - 破坏Toast的处理程序依赖的线程上。
在runnable中播放toast是有效的,因为此时,当前线程是UI线程。