今天在进行自测的时候,偶然发现了一个crash。场景时在用户第一次安装登录时,点击登录出现闪退。
报错日志如下:
08-10 18:19:04.021 E/AndroidRuntime(24334): java.lang.RuntimeException: Unable to pause activity {*****(packageName)/*****(packageName).MainActivity}: java.lang.IllegalArgumentException: Receiver not registered: null
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3736)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3695)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3670)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ActivityThread.access$1100(ActivityThread.java:177)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1459)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.os.Handler.dispatchMessage(Handler.java:102)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.os.Looper.loop(Looper.java:145)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ActivityThread.main(ActivityThread.java:5942)
08-10 18:19:04.021 E/AndroidRuntime(24334): at java.lang.reflect.Method.invoke(Native Method)
08-10 18:19:04.021 E/AndroidRuntime(24334): at java.lang.reflect.Method.invoke(Method.java:372)
08-10 18:19:04.021 E/AndroidRuntime(24334): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
08-10 18:19:04.021 E/AndroidRuntime(24334): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
08-10 18:19:04.021 E/AndroidRuntime(24334): Caused by: java.lang.IllegalArgumentException: Receiver not registered: null
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:822)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:2038)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:528)
08-10 18:19:04.021 E/AndroidRuntime(24334): at *****(packageName).MyFragment.onPause(MyFragment.java:185)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.support.v4.app.Fragment.performPause(Fragment.java:1950)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1005)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.support.v4.app.FragmentManagerImpl.dispatchPause(FragmentManager.java:1943)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.support.v4.app.FragmentActivity.onPause(FragmentActivity.java:393)
08-10 18:19:04.021 E/AndroidRuntime(24334): at com.fiberhome.smarthome.BaseActivity.onPause(BaseActivity.java:63)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.Activity.performPause(Activity.java:6447)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1308)
08-10 18:19:04.021 E/AndroidRuntime(24334): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3722)
08-10 18:19:04.021 E/AndroidRuntime(24334): ... 11 more
崩溃的原因很简单:在没有调用过registerReceiver的情况下,程序调用unregisterReceiver进行解绑操作。
刚接手的新项目,粗略一看onResume和onPause中分别调用registerReceiver和unregisterReceiver方法。那么为什么还是会出现这种错误呢。
再仔细一看,onResume代码中有一句判断引起了我的注意。在token为空的情况下,函数已经返回了,并未进行registerReceiver的流程。具体改动如下图:
这也给我一个警示,在调用registerReceiver和unregisterReceiver时,必须保持顺序性。可在onCreate/onDestroy;onResume/onPause组合中调用。注意不要在onCreate中调用registerReceiver,而在onStop/onPause中调用unregisterReceiver,因为二者声明周期不对称;可能出现调用unregisterReceiver比registerReceiver次数多的问题。