【问题标题】:IntentService won't show ToastIntentService 不会显示 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!
}
}

【问题讨论】:

标签: android intentservice android-toast


【解决方案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 新手。

    【讨论】:

      猜你喜欢
      • 2011-03-18
      • 1970-01-01
      • 2014-07-04
      • 2015-06-15
      • 2016-12-13
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多