概述
内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。用完没有释放,造成可用内存越来越少。这里就不得不提一下Java GC机制和Java四种引用方式
在实际项目中稍有不慎就有可能导致内存泄露,下面梳理一下常见的可能造成内存泄露的代码和解决办法
Handler
在Android的多线程开发中,估计永远无法绕开handler了(不知道kotlin的协程是怎么实现的?),但是使用Handler却很容易出现问题,看下面代码:
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
Message message = new Message();
handler.sendMessageDelayed(message,2000);
复制代码
不幸的告诉你,这段代码已经造成了内存泄露。
首先需要知道的是:非静态内部类默认持有外部类的引用message send出去的时候,会进入MessageQueue中,Looper会不停的从MessageQueue中取出Message并分发执行。如果message没有被执行完毕,handler就不会被释放,如果此时activity被销毁了,由于Handler持有当前Activity的引用,Handler没有被释放,其所持有的外部引用也就是Activity也不可能被释放。jvm无法对activity执行GC,Activity就泄漏。
解决办法:
public static class MyHandler extends Handler{
WeakReference reference;
public MyHandler(WeakReference activity){
reference = activity;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (reference.get()!=null){
//注意必须要要进行判空
}
}
}
复制代码调用Handler.removeMessages()
在onDestory中可以将handler中的message都移除掉,没有延时任务要处理,activity的生命周期就不会被延长,则可以正常销毁。
单例
public class Initializer {
private Initializer instance;
private Context context;
private MyHelper(Context context){
this.context = context;
}
public static synchronized Initializer getInstance(Context context){
if (instance == null){
instance = new Initializer(context);
}
return instance;
}
}
复制代码
当需要Context对象进行初始化时,如果错误的使用:
Initializer.getInstance(this)
复制代码
就会存在内存泄露的风险,因为单例中的static实例持有Activity,但是static变量的生命周期是整个应用的生命周期,当Activity finish时,activity实例被static变量持有不能释放内存,导致内存泄漏。
解决办法:
使用getApplicationContext()
在Application里初始化,或者使用getApplicationContext()作为Context
匿名内部类
泄露原因和Handler一样,解决方案也类似,静态内部类+弱引用方式调用就行了。
RxJava和网络请求
如果网络请求数据返回缓慢,Activity在请求成功之前就被结束,但是这时网络请求还未结束,回调接口为内部类依然会持有Activity的对象,这时Activity就内存泄漏的。
解决办法就是接触回调监听,可以使用lifecycle管理生命周期或者直接使用jetpack中的LiveData组件。
最后
以上就是大意草莓为你收集整理的android内存泄露解决,Android常见内存泄露和解决办法的全部内容,希望文章能够帮你解决android内存泄露解决,Android常见内存泄露和解决办法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复