ConnectivityManager内存泄露
在APP中使用了ConnectivityManager
来进行网络判断,然后竟然莫名其妙的内存泄露了…一脸懵逼.
觉得直接看一遍作用不大,于是自己跟着源码来进行一次分析
Context
|
|
首先Activity的Context都知道其实是一个ContextImpl对象.那么调用的自然也就是ContextImpl的getSystemService(String name)
方法.
代码如下
|
|
很明显这里调用了静态类的静态方法,进而返回了ConnectivityManager
对象,进而导致内存泄露.
SystemServiceRegistry
很明显就是在SystemServiceRegistry调用静态方法中出现了问题.该方法调用了静态对象进行查找并返回,代码如下:
|
|
方法中先是进行查到,返回一个ServiceFetcher对象,并且调用其getService(ContextImpl ctx)
方法,来返回用到的ConnectivityManager对象.
而SYSTEM_SERVICE_FETCHERS初始化是在静态语句块中完成的.通过Context.CONNECTIVITY_SERVICE在静态语句块中找到了其注册过程.代码如下:
|
|
StaticOuterContextServiceFetcher
由此可以看到在SystemServiceRegistry查找的方法中返回的是一个StaticOuterContextServiceFetcher对象.我感觉真相理我不远了(看了一遍别人分析的也好意思说...)
StaticOuterContextServiceFetcher对象代码如下:
这里就很清晰了,在调用getService(ContextImpl ctx)
时候调用了createService(Context applicationContext)
方法,传递过去的Context对象为ContextImpl.getOuterContext()返回的mOuterContext
对象,而mOuterContext
对象是在ContextImpl创建的时候进行的初始化mOuterContext = this;
,也就是其本身.
再看SystemServiceRegistry中实现的createService()
方法.它利用Context创建并返回了一个ConnectivityManager对象
ConnectivityManager
|
|
这里可以看到ConnectivityManager是个单例对象,并且持有了Context的对象引用,即ContextImpl的mOuterContext
对象,也就是自己.也就是Activity的Context.
到这里就水落石出了,坑爹的ConnectivityManager竟然是单例对象,还会持有调用对象的Context对象,我傻傻的用Activity去获取,自然导致Activity内存泄露,无法被释放.
解决办法
单例对象自然寿与天齐,Activity肯定是不能真么干的,那么就给他寿与天齐的Context对象即可.