内存泄漏的问题,其实就是已经过期的对象仍被引用(非过期对象互相引用),导致已经过期的对象不能被GC自动回收的问题。
1、把过期的对象引用作为参数传给了还有生命周期的方法,如线程、计时器需等方法执行完毕才会释放内存;2、非静态内部类引用过期对象,如Handler、AsyncTask需等类对象生命周期结束才会释放内存;3、有生命周期的对象变量引用过期对象,如单例对象持有context,直到程序生命周期结束才会释放内存,再如一些监听,直到取消监听才会释放内存;4、资源对象引用过期对象,知道资源对象关闭才会释放内存。
分析内存泄漏:使用LeakCanary三方jar包;使用Android Profiler工具,进行一些操作如多次进出一个页面并手动GC,观察内存变化情况,然后按包名查找查看是否有多个实例。
解决方法:1、使用弱引用;2、及时解除引用。
内存回收相关问题:为什么尽量不要在onDraw()方法中创建paint对象?
View 的 onDraw() 方法会被频繁的调用,而垃圾回收器工作时,会停止此虚拟机中的一切线程,等垃圾回收器工作完成,程序线程才能再次工作。
MVC、MVP、MVVM模式使用的原因:为了更好的分离Model与View。这里的V既指view也指activity。Model持有已过期activity,如果没有及时断开数据库或者网络连接,就会发生内存泄漏。
MVC:在Controller中分离Model和View。
MVP、MVVM:使用专门的类来管理Model与View的连接与分离,方便只修改代码与测试。
MVP:因为Controller有可能是Activity也有能是Adapter,所以使用了Presenter来专门进行Model和View的分离工作。因为activity(adapter)本身就是View层,所以需要实现View接口;同时持有Presenter对象,调用Presenter的方法。而Presenter持有View接口,并调用View接口方法,建立Model和View的联系。
MVVM:在ViewModel中进行Model和View的连接与断开。
使用Google提供的AAC(Android Architecture Components),在Model(分为本地SQL和网络webservice)和ViewModel之间添加一个Repository。Repository通过本地SQL或者网络来获取Model对象,一旦本地SQL或者网络发生变化,Repository就发生变化。activity新建时,通过View Model来建立View和Repository的连接(实质还是View与Model产生关系);activity销毁时,通过ViewModel断开View和Repository的连接,再销毁View。Google提供的ViewModel已经封装了在activity销毁时断开连接的操作,即在activity销毁时调用ViewModel的onCleared()方法。但通常onCleared()方法并不会去实现,而是采用LiveData来实现。LiveData的observe方法会绑定具有生命周期的对象,并在这个绑定的对象被销毁后自行清理。也就说如果不是使用LiveData那么就要重写onCleared()方法了。