BroadcastReceiver生命周期探讨

来源:互联网 发布:人人店三级分销源码 编辑:程序博客网 时间:2024/05/29 12:27

前言

之前做线控耳机连点两下切下一首歌的需求时, 曾经尝试在BroadcastReceiver中用一个成员变量保存最后一次按下的时间, 但后来发现这个值一直是初始值, 对它赋值后, 再次收到Intent时发现它的值又变成初始值了.
后来看到一些问题, 问BroadcastReceiver的生命周期, 按理说它就一个onReceive能有什么生命周期, 其实这里问的生命周期和我们平时说的Activity的生命周期还是有区别的.

BroadcastReceiver对象的生命周期

问题的根源在于, 在AndroidManifest.xml中注册的BroadcastReceiver, 每次收到一个Intent, 也就是onReceive被回调的时候, 这个BroadcastReceiver都是新创建出来的, 官方文档中写:

A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.

也就是说, 出了onReceive, 这个BroadcastReceiver对象的生命周期就已经到头了, 这也是为什么我们不能在onReceive中进行一些异步操作的原因, 有可能异步操作还没完成, BroadcastReceiver所在的进程就被kill了.
表现出来的结果就是, BroadcastReceiver中的成员变量无法保存它们的值, 因为它们每次都是重新创建的, 之前的已经随着BroadcastReceiver对象被销毁了.
但是有一种情况, BroadcastReceiver的成员变量是可用的, 那就是动态注册的BroadcastReceiver. 动态注册的BroadcastReceiver对象的生命其实是受我们控制的.
实际测试, 使用Context.registerReceiverContext.unregisterReceiver注册的BroadcastReceiver每次收到广播都是使用我们注册时传入的对象处理的, 这也是符合我们代码上的逻辑的. 当然, 此时静态变量也是可用的.

BroadcastReceiver所在进程的生命周期

对于那种在AndroidManifest.xml中静态注册的BroadcastReceiver, 成员变量是没法用了, 有人说, 是不是用static变量就可以了呢, 某些情况下是可以的, 什么情况呢, 就是进程不会被kill的情况.
官方文档里面有一段

Once you return from onReceive(), the BroadcastReceiver is no longer active, and its hosting process is only as important as any other application components that are running in it.

AndroidManifest.xml中静态注册的BroadcastReceiveronReceive被回调时, 有可能这个进程只承载了这个BroadcastReceiver, 比如我们的应用没有运行的情况, 等onReceive返回, 这个时候我们的进程的会被视为空进程(empty process), 此时Android有极大可能回收掉空进程, 这种情况下静态成员变量也无法保存值了.

如果我们的程序正在运行, 则Android不一定会回收掉我们的进程, 因为此时我们的进程级别会以进程中承载的级别最高的组件为准. 在我的实际项目中, 我是在播放歌曲的情况下监听线控耳机的按下Intent, 这个时候我的应用是有一个前台服务播放歌曲的, 此时我的进程至少是可见进程(visible process)级别, 几乎不会被Android kill掉, 所以我可以在BroadcastReceiver中使用一个静态成员变量记录上一次点击的时间.

以上是个人研究后的结果, 如果有误, 欢迎批评指正.

0 0