Receiver和Service是如何做到和Activity的生命周期绑定的?

在Activity中registeReceiver或者bindService,如果Activity销毁时还没进行unregisterReceiver或者unbindService,就会出现如下错误:

1、未调用unregisterReceiver:android.app.IntentReceiverLeaked: Activity xxxxx has leaked

2、未调用unbindService:android.app.ServiceConnectionLeaked: Activity xxxxx has leaked

出现这两个错误的原因是:Activity在退出后会调用onDestroy方法,然后会释放一些资源,流程如下:

《Receiver和Service是如何做到和Activity的生命周期绑定的?》 finishActivity流程图

最终运行LoadedApk.removeContextRegistrations,该方法就是用来实现Receiver和Service的泄漏处理。

《Receiver和Service是如何做到和Activity的生命周期绑定的?》 检测Activity的receiver释放leak

在Activity.finish后如果没有调用unregisterReceiver,就会出现泄漏。其中mReceivers是当前App注册的所有Receiver,在如果rmap不为空,且size大于0,说明Activity对应的Context中的Receiver还没有回收,Receiver会引用Activity,Activity就存在Leak。那么mReceiver中的值是哪里来的呢?答案就是regeisterReceiver函数,流程如下:

《Receiver和Service是如何做到和Activity的生命周期绑定的?》 register unregister流程

在注册广播的时候调用LoadedApk.getReceiverDispatcher会将BroadcastReceiver存储到mReceiver中,unRegisterReceiver会通过forgetReceiverDispatcher将BroadcastReceiver从mReceiver中移除,如果没有unRegisterReceiver,在退出Activity就会出现android.app.IntentReceiverLeaked: Activity xxxxx has leaked错误。

《Receiver和Service是如何做到和Activity的生命周期绑定的?》 检查Service是否泄漏

如果smap中Activity的Context对应的ServiceDispatcher不为空,说明Activity在调用bindService后没有主动调用unbindService,而ServiceConnectin会引用Activity,Activity就会存在Leak。流程和Receiver类似:

《Receiver和Service是如何做到和Activity的生命周期绑定的?》 bindService unbindService

bindService或调用LoadedApk.getServiceDispatcher将ServiceDispatcher加入mService中,unbindService通过forgetServiceDispatcher将ServiceDispatcher进行移除。如果不调用unbindService就会出现Activity Leak。

但是在APP运行的时候并没有出现Crash,是因为LoadedApk.removeContextRegistrations只是打印了泄漏信息,之后会再次调用AMS的unregisterReceiver或者unbindService。

因此,Receiver和bindService可以实现和Activity生命周期的联动。

    原文作者:JasmineBen
    原文地址: https://www.jianshu.com/p/9f1729e3b8a7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞