【发布时间】:2014-04-03 23:58:08
【问题描述】:
我开发了一个小型 Android 应用程序,它使用 AlarmManager 来调用处理程序线程,该线程将移动设备的一些信息与远程服务器同步。此过程每 15 分钟发生一次。
当我在没有 AlarmManager 帮助的情况下使用 HandlerThread 时,一切总是工作正常。但是,当我尝试将这两者结合在一起时,SOMETIMES 会起作用,SOMETIMES 会出现以下错误:
W/System.err(10557): java.lang.NullPointerException
W/System.err(10557):at Synchronizer.queueSyncEverything(Synchronizer.java:109)
W/System.err(10557): at SyncService.onHandleIntent(SyncService.java:33)
W/System.err(10557): at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
W/System.err(10557): at android.os.Handler.dispatchMessage(Handler.java:99)<BR/>
W/System.err(10557): at android.os.Looper.loop(Looper.java:137)
W/System.err(10557): at android.os.HandlerThread.run(HandlerThread.java:60)
代码非常简单,你可以在下面的 sn-ps 中看到:
//Method from SyncService, a class which extends IntentService
protected void onHandleIntent(Intent intent) {
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
if(cm.getActiveNetworkInfo() == null){
return;
}
if(mSynchronizer == null){
mSynchronizer = new Synchronizer(getApplicationContext(), this);
mSynchronizer.start();
mSynchronizer.getLooper();
}
mSynchronizer.queueSyncEverything();
}
//Method from Synchronizer, a class which extends HandlerThread
public void queueSyncEverything(){
try{
mHandler.obtainMessage(MESSAGE_SYNC_EVERYTHING).sendToTarget();
}
catch(Exception e){
mListener.onError();
e.printStackTrace();
}
}
我已经检查了Handler或Looper是否为null,但它们都很好。
编辑: 正如@DavidWasser 建议的那样,我进行了更多测试,发现有时 mHandler 为空。这个变量是在 Synchronizer(从 HandlerThread 扩展)的 onLooperPrepared 方法中设置的,你可以在这里看到:
@Override
protected void onLooperPrepared(){
mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_SYNC_EVERYTHING){
handleSyncEverything();
mListener.onFinished();
}
}
};
}
正如@DavidWasser 所问的,这个类的构造函数只是:
public Synchronizer(Synchronizer.Listener listener){
super(TAG);
mListener = listener;
}
mListener 只是一个类似委托的对象,它接收 Synchronizer 类发送的事件,例如同步完成时。 TAG 只是一个便于调试的名称。也许我的主要困难是理解 HandlerThread 类是如何工作的,什么时候设置它的 Handler 对象合适。
P.S.:这种设置 HandlerThread 的方法是我通过阅读《Android 编程:大书呆子牧场指南》一书得到的。
【问题讨论】:
-
我假设第 109 行是
mHandler.obtainMessage(MESSAGE_SYNC_EVERYTHING).sendToTarget();和mHandler为空。您在哪里将该变量设置为?还要贴出闹钟响起时调用的代码。 -
@DavidWasser,刚刚做了一些测试,是的,mHandler 为空。它设置在 Synchronizer (HandlerThread) 的 onLooperPrepared 方法中,您可以在此处看到:
protected void onLooperPrepared(){ mHandler = new Handler(){ @Override public void handleMessage(Message msg){ if(msg.what == MESSAGE_SYNC_EVERYTHING){ handleSyncEverything(); mListener.onFinished(); } } }; }据我所知,调用 mSynchronizer.getLooper() 时会调用此方法。闹钟响起时调用的方法太大了,只是对远程服务器的一些调用。 -
发现很难遵循您的代码。请不要在 cmets 中添加代码 sn-ps。只需编辑您的问题并将代码添加到原始问题。
Synchronizer来自什么?请显示该类的构造函数 -
对不起,@David,这是我第一次在 StackOverflow 上发帖,所以我不习惯使用约定和文本编辑器的工作方式。我刚刚编辑了问题并添加了您问我的信息。谢谢!
-
处理程序在 onLooperPrepared 中初始化,但您没有给它时间准备。你应该打电话给
queueSyncEverythingonLooperPrepared
标签: android alarmmanager android-pendingintent android-handler