在Android中使用AlarmManager时的Intermitent NullPointerException

时间:2014-03-03 03:39:14

标签: android alarmmanager android-pendingintent android-handler

我开发了一个小型的Android应用程序,它使用AlarmManager来调用Handler Thread,它将来自移动设备的某些信息与远程服务器同步。这个过程每15分钟发生一次。

当我在没有AlarmManager的帮助下使用HandlerThread时,始终的所有内容都可正常工作。但是,当我尝试将这两者结合使用时,有时它可以正常工作,有时我收到以下错误:

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)

代码非常简单,您可以在以下代码段中看到:

//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是null。这个变量在Synchronizer的方法onLooperPrepared中设置(从HandlerThread扩展),如下所示:

@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。:通过阅读“Android编程:大书呆子牧场指南”这本书,我设置了HandlerThread。

1 个答案:

答案 0 :(得分:0)

请勿在{{1​​}}中初始化mHandler,因为在onLooperPrepared()调用后,此方法可以被称为。这是一个可以咬你的小时间窗口。

而是在getLooper()中创建一个方法,如下所示:

Synchronizer

并在public void createHandler() { mHander = new Handler(getLooper()) { @Override public void handleMessage(Message msg){ if(msg.what == MESSAGE_SYNC_EVERYTHING){ handleSyncEverything(); mListener.onFinished(); } } }; } 中调用此方法,而不是调用onHandleIntent()

这将确保mSynchronizer.getLooper()在<{>> 之前初始化 mHandler

注意:您根本不需要覆盖queueSyncEverything()