博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Handler系列之内存泄漏
阅读量:5924 次
发布时间:2019-06-19

本文共 3375 字,大约阅读时间需要 11 分钟。

hot3.png

什么是内存泄漏?大白话讲就是分配出去的内存,回收不回来。严重会导致内存不足OOM。下面来看一下造成内存泄漏的代码:

复制代码

public class MemoryLeakActivity extends Activity {    private MyHandler mHandler;        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_handler);        mHandler = new MyHandler();        mHandler.sendEmptyMessage(1);    }    private class MyHandler extends Handler{                public MyHandler(){        }                @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);        }    }}

复制代码

上面的代码我们不用管发送消息、接受消息,因为之前已经详细讲过了,不是本篇的重点。本篇我想说上面的代码会造成内存泄漏,什么意思?Handler持有MemoryLeakActivity引用,为什么?如果不持有当前类的引用,我怎么更改当前类的ui或其他逻辑???或者我们知道内部类持有外部类引用也行。那么怎么解决那?

  解决办法:将内部类改为静态内部类,因为静态内部类不持有外部类引用。由于Handler不再持有外部类引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你还需要在Handler中增加一个对Activity的弱引用(使用弱引用的好处在于:activity一旦被置为null,他就会被立刻回收)。上面持有的引用属于强引用,强引用的特点就是当当前类被回收的时候,如果它被强引用所持有,那么当前类是不会被回收的!!!所以我们改成软引用持有当前类对象,这样在GC回收时会忽略掉弱引用,即就算有弱引用指向某对象,该对象也会在被GC检查到时回收掉。

复制代码

public class MemoryLeakActivity extends Activity {    private MyHandler myHandler;    private static final int ACTION_GOTO_MAIN = 1001;    private static final int GOTO_MAIN_TIMER = 2 * 1000;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_handler);        myHandler = new MyHandler(this);    }    @Override    protected void onResume() {        super.onResume();        if (myHandler != null) {            myHandler.sendEmptyMessageDelayed(ACTION_GOTO_MAIN, GOTO_MAIN_TIMER);        }    }    @Override    protected void onPause() {        super.onPause();        if (myHandler != null && myHandler.hasMessages(ACTION_GOTO_MAIN)) {            myHandler.removeMessages(ACTION_GOTO_MAIN);        }    }    protected static class MyHandler extends Handler {        private WeakReference
mActivity; public MyHandler(MemoryLeakActivity activity) { mActivity = new WeakReference
(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); MemoryLeakActivity activity = mActivity.get(); if (activity == null) return; if (msg.what == ACTION_GOTO_MAIN) { //处理逻辑 } } }}

复制代码

上面代码很好的解决了内存泄漏的问题。但是这段代码可能会在很多界面都会遇到,难道每个界面都需要这样写吗?重复的工作啊,所以干脆我们抽取成一个基类,将来创建Handler的时候继承这个基类就好。

复制代码

public abstract class WeakHandler
extends Handler { protected WeakReference
reference; //创建子线程Handler使用的构造器 public WeakHandler(Looper looper, T reference) { super(looper); this.reference = new WeakReference<>(reference); } //创建主线程Handler使用的构造器 public WeakHandler(T reference) { this.reference = new WeakReference<>(reference); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); T t = reference.get(); if (t == null) return; handleMessage(t, msg); } protected abstract void handleMessage(T t, Message message);}

复制代码

上述代码,我们使用了泛型,这个泛型就是我们之前说的当前类,同时提供了两种构造器,这样不管我们是创建主线程还是非主线程Handler对象时,都不会造成内存泄漏了。

  至此,Handelr系列讲解到此结束,大多数都是参数慕课网的《Android面试常客Handler详解》,我这里只是将视频中的内容加上自己的理解纪录下来,希望对大家有所帮助。

原文:

转载于:https://my.oschina.net/yuerliang/blog/820883

你可能感兴趣的文章
杠上Spark、Flink?Kafka为何转型流数据平台
查看>>
分类模型的评价方法
查看>>
微服务系列-Spring Cloud优质项目推荐
查看>>
11-玩转数据结构-并查集
查看>>
Android--List转换String,String转换List
查看>>
Java码农必须掌握的循环删除List元素的正确方法!
查看>>
Gradle Distributions
查看>>
.Net Micro Framework开发板用户简明手册
查看>>
基于事件驱动的DDD领域驱动设计框架分享(附源代码)
查看>>
国信灵通:企业移动化改变生活
查看>>
互联网金融带来新机遇 数据合规性不容忽视
查看>>
不可不知:测试云计算服务的九个窍门
查看>>
《Apache Zookeeper 官方文档》-1简介
查看>>
恶补web之七:html DOM知识
查看>>
Linux备份ifcfg-eth0文件导致的网络故障问题
查看>>
第二天 web 笔记
查看>>
前端知识点总结——VUE
查看>>
2018年尾总结——稳中成长
查看>>
xampp下新增virtualhost出现access denied
查看>>
多IP主机用于挂协议挂游戏有什么好处!
查看>>