在死线程上向处理程序发送消息

Mit*_*ina 25 android

我正在开发一个后台服务,在一段时间内对服务器进行轮询.关键是:我有一个调用另一个服务的IntentService(称为NotificationsService),但是这个请求的响应没有回来.并在logcat中出现:

06-19 05:12:00.151: W/MessageQueue(6436): Handler (android.os.Handler) {416659f0} sending message to a Handler on a dead thread
06-19 05:12:00.151: W/MessageQueue(6436): java.lang.RuntimeException: Handler (android.os.Handler) {416659f0} sending message to a Handler on a dead thread
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:196)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.Handler.sendMessageAtTime(Handler.java:473)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.Handler.sendMessageDelayed(Handler.java:446)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.Handler.post(Handler.java:263)
06-19 05:12:00.151: W/MessageQueue(6436):   at android.os.ResultReceiver$MyResultReceiver.send(ResultReceiver.java:50)
Run Code Online (Sandbox Code Playgroud)

我在这里看到类似的问题,但我感到困惑(我没有使用任何AsyncTask,我已经找了CommonsWare代码wakefullIntent但我不理解它).

这是NotificationsService.java的代码

public class NotificationsService extends IntentService {
private static  int TIME_INTERVAL_MILIS=90000;
private static final int REFRESH=10;
private  NotificationManager noteManager;
private static List<FlightStatusNote> flights= new ArrayList<FlightStatusNote>();



public NotificationsService(){
    super("NotificationsService");

}

@Override
public void onCreate(){
    Log.d("notificationsSservice","onCreate");
    super.onCreate();
    noteManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
}



@Override
protected void onHandleIntent(Intent intent) {
    Log.d("NotificationsService","Me llamaron");

    Log.d("NotificationsService", "intervalo:"+NotificationsService.TIME_INTERVAL_MILIS);
        Log.d("NotificationsService","Itero por cada vuelo registrado para notificar");
        for(FlightStatusNote f: flights){
            FlightStatus fly=f.getFlight();
            Log.d("NotificationsService","Vuelo id:"+fly.getAirlineId()+fly.getNumberFlight());
            Intent intentaux=new Intent(Intent.ACTION_SYNC,null,getBaseContext(),FlightStatusService.class);
            intentaux.putExtra("airlineFlight", fly.getAirlineId());
            intentaux.putExtra("numberFlight",fly.getNumberFlight() );
            intentaux.putExtra("receiver", new ResultReceiver(new Handler()) {

                @Override
                protected void onReceiveResult(int resultCode, Bundle resultData) {
                    super.onReceiveResult(resultCode, resultData);
                    Log.d("notificationsService","response received");
                    if (resultCode == FlightStatusService.STATUS_OK) {
                        List<FlightStatus> fly =  (List<FlightStatus>)resultData.getSerializable("return");
                        for(FlightStatus f: fly){
                            int indexNote=flights.indexOf(new FlightStatusNote(f,null));
                            FlightStatusNote fsNote=flights.get(indexNote);
                            List<String> changes=fsNote.hasChanged(f);
                            if(changes==null){
                                Log.d("notificationsService","changes is null");
                            }
                            else{
                                Log.d("notficationsService", "comething changed");
                                createNotification(f, changes);
                            }

                        }


                    }

                }

            });
            startService(intentaux);
    }

        AlarmManager alarmMgr = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
          PendingIntent pendingIntent =  PendingIntent.getBroadcast(getBaseContext(), 0, new Intent(getBaseContext(), DealAlarmReceiver.class), 0);
          alarmMgr.set(AlarmManager.RTC, System.currentTimeMillis()+NotificationsService.TIME_INTERVAL_MILIS, pendingIntent);

}
}
Run Code Online (Sandbox Code Playgroud)

如果有人可以帮助我,我会非常感激!干杯!

编辑:我认为问题是日志"收到响应"它没有出现.

jpa*_*alm 25

IntentService在调用onHandleIntent方法时创建一个新线程,然后在该onHandleIntent方法返回后立即终止该线程.

你需要在其他地方创建你的监听器,IntentService因为他们死了,所以设置监听器是不安全的.它们主要用于在主线程之外执行短任务.在这里查看类似的问题.

编辑:另请参阅有关IntentService的文档.

  • 我已经读过类似的问题,但我仍然被卡住了.我应该在哪里创建听众? (3认同)

小智 5

我不能回复,因为我是新人,但基本上'jpalm'提到的是最准确的答案.

基本上我有一个与ServiceIntent一起玩的东西:他们会在他们完成后立即死掉.这意味着如果你在框架中提交作品(比如开始一个Activity); 框架可以立即回复给你,告诉你'startService(intentaux)'返回OK或者其他什么(我不是专家,我也是新手:P),因为它发现你的线程已经死了! !!.

当您启动Activity时,如果您故意强制您的线程以某种方式存活,直到您收到响应,则不会发生此错误.

请参阅http://developer.android.com/guide/components/services.html.将示例修改为不等待,然后Toast开始崩溃发送这样的清除消息,即使您认为您没有使用ASYNC方法.

07-24 08:03:16.309: W/MessageQueue(1937): java.lang.RuntimeException: Handler (android.os.Handler) {b1016d80} sending message to a Handler on a dead thread
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:320)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.enqueueMessage(Handler.java:626)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.sendMessageAtTime(Handler.java:595)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.sendMessageDelayed(Handler.java:566)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Handler.post(Handler.java:326)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.widget.Toast$TN.hide(Toast.java:370)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.app.ITransientNotification$Stub.onTransact(ITransientNotification.java:55)
07-24 08:03:16.309: W/MessageQueue(1937):   at android.os.Binder.execTransact(Binder.java:404)
07-24 08:03:16.309: W/MessageQueue(1937):   at dalvik.system.NativeStart.run(Native Method)
Run Code Online (Sandbox Code Playgroud)

我不得不说android.developers的文档非常好但非常简洁(ULTRA ZIP),这意味着你必须逐字阅读和阅读,然后当你在绝望之后查看字典时......你说:它总是在这里!:o

它就像一本圣经,但对于开发者来说:)不知怎的,我们正在成为Android的先知:P


Jef*_*man 5

每个Handler都有一个Looper,一个Looper有一个HandlerThread.一般问题是当a Handler与停止运行的线程相关联时.如果有人试图使用Handler它,它将失败并显示消息"在死线程上向处理程序发送消息".

如果你这样做,new Handler()它就会与当前线程相关联(相反,它会与Looper关联的w /当前线程相关联).如果你在一个即将消失的线程上执行此操作(例如一个工作线程IntentService),你就会遇到问题.问题当然不仅限于这个根本原因,它可以以多种方式发生.

任何简单的解决方法就是构建你的Handler喜欢,

Handler h = new Handler(Looper.getMainLooper());
Run Code Online (Sandbox Code Playgroud)

这将Handler与主循环器或永不消亡的主应用程序线程相关联.另一个更复杂的解决方案是为其创建一个专用线程Handler,

HandlerThread ht = new HandlerThread(getClass().getName());
ht.start();
Handler handler = new Handler(ht.getLooper());
Run Code Online (Sandbox Code Playgroud)

请注意,您需要明确quit()HandlerThread,当你与关联的完成Handler.