IntentService 不会显示 Toast
Posted
技术标签:
【中文标题】IntentService 不会显示 Toast【英文标题】:IntentService won't show Toast 【发布时间】:2011-07-17 20:20:06 【问题描述】:我创建的这个 IntentService 将在 onStartCommand() 和 onDestroy() 中显示 Toast,但不会在 onHandleIntent() 中显示。我是否遗漏了有关 IntentService 限制的一些信息?
public class MyService extends IntentService
private static final String TAG = "MyService";
public MyService()
super("MyService");
@Override
protected void onHandleIntent(Intent intent)
cycle();
@Override
public int onStartCommand(Intent intent, int flags, int startId)
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); //This happens!
return super.onStartCommand(intent,flags,startId);
@Override
public void onCreate()
super.onCreate();
@Override
public void onDestroy()
Toast.makeText(this, "service stopping", Toast.LENGTH_SHORT).show(); //This happens!
super.onDestroy();
private void cycle()
Toast.makeText(this, "cycle done", Toast.LENGTH_SHORT).show(); //This DOESN'T happen!
Log.d(TAG,"cycle completed"); //This happens!
【问题讨论】:
create toast from IntentService 的可能重复项 【参考方案1】:接受的答案不正确。
下面是如何显示来自onHandleIntent()
的吐司:
Create a DisplayToast class:
public class DisplayToast implements Runnable
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text)
this.mContext = mContext;
mText = text;
public void run()
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
在服务的构造函数中实例化一个Handler
,并调用带有DisplayToast
对象的post
方法。
public class MyService extends IntentService
Handler mHandler;
public MyService()
super("MyService");
mHandler = new Handler();
@Override
protected void onHandleIntent(Intent intent)
mHandler.post(new DisplayToast(this, "Hello World!"));
【讨论】:
该死的太聪明了。我希望有一个关于堆栈溢出的提示机器人,所以我可以给你狗狗币一个很好的答案。 IIRC,这类似于我解决问题的方式。接受的答案是正确的,并且您的答案提供了如何绕过它的详细信息(将其提交给处理程序,以便在正确的线程上调用它。 这个处理程序不会绑定到当前线程而不是主线程吗? Dianne Hackborne 并没有说这是不可能的,只是说你不应该从后台线程做 UI。传递上下文对象是一件繁重的事情,并且可能导致泄漏。接受的答案是最好的答案,而这个答案是一种解决方法。 为什么如果我将 mHandler 的初始化移动到 onHandleIntent 方法这个代码不起作用?为什么一定要在构造函数中声明?【参考方案2】:你应该在主线程上启动 Toast:
new Handler(Looper.getMainLooper()).post(new Runnable()
@Override
public void run()
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
);
这是因为否则 IntentService 的线程在 toast 可以发出之前退出,导致 IllegalStateException:
java.lang.IllegalStateException: Handler (android.os.Handler) 12345678 向死线程上的 Handler 发送消息
【讨论】:
【参考方案3】:onHandleIntent() 是从后台线程调用的(这就是 IntentService 的全部意义所在),所以你不应该从那里做 UI。
【讨论】:
就是这样,谢谢!我在 onStartCommand() 中创建了一个处理程序字段并将 Toast 发布到处理程序并且它起作用了。【参考方案4】:另一个选项是RxJava,例如:
private void showToast(final String text)
Observable.just(text)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>()
@Override
public void call(String s)
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
);
警告:我是 Android 新手。
【讨论】:
以上是关于IntentService 不会显示 Toast的主要内容,如果未能解决你的问题,请参考以下文章
GCM:如果应用程序不可见,则不会收到 IntentService.sentBroadcast 的消息