一. WeakReference:防止内存泄漏,要保证内存被虚拟机回收。

例子分析:首先我们来看一段代码

public class AutoActivity extends Activity {

    Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg) {

        };
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auto);
    }
}

上面这段低吗没有什么问题,但是在handler对象创建的时候却会报警告:This Handler class should be static or leaks might occur意思是:Handler类应该为static类型,否则可能会造成内存泄漏。为什么会造成这种情况呢?

这种情况就是由于android的特殊机制造成的:当一个android主线程被创建的时候,同时会有一个Looper对象被创建,而这个Looper对象会实现一个MessageQueue(消息队列),当我们创建一个handler对象时,而handler的作用就是放入和取出消息从这个消息队列中,每当我们通过handler将一个msg放入消息队列时,这个msg就会持有一个handler对象的引用。因此当Activity被结束后,这个msg在被取出来之前,这msg会继续存活,但是这个msg持有handler的引用,而handler在Activity中创建,会持有Activity的引用,因而当Activity结束后,Activity对象并不能够被gc回收,因而出现内存泄漏。

这个根本原因就是:Activity在被结束之后,MessageQueue并不会随之被结束,如果这个消息队列中存在msg,则导致持有handler的引用,但是又由于Activity被结束了,msg无法被处理,从而导致永久持有handler对象,handler永久持有Activity对象,于是发生内存泄漏。但是为什么为static类型就会解决这个问题呢?因为在java中所有非静态的对象都会持有当前类的强引用,而静态对象则只会持有当前类的弱引用。声明为静态后,handler将会持有一个Activity的弱引用,而弱引用会很容易被gc回收,这样就能解决Activity结束后,gc却无法回收的情况。

所以解决这个警告就有几种方法:
一:将hanlder对象声明为静态的对象。
二:使用静态内部类,通过WeakReference实现对Activity的弱引用。具体实现看以下代码:

public class AutoActivity extends Activity {

    MyHandler handler = new MyHandler(this);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auto);
    }

    static class MyHandler extends Handler{
        WeakReference<AutoActivity> mactivity;

        public MyHandler(AutoActivity activity){
            mactivity = new WeakReference<AutoActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);           
            switch (msg.what) {
            case 100:               
                //在这里面处理msg
                //通过mactivity.get()获取Activity的引用(即上下文context)
                break;              
            default:
                break;
            }
        }
    }
}

二. SoftReference:实现缓存机制

例如从网络上获取图片,然后将获取的图片显示的同时,通过软引用缓存起来。当下次再去网络上获取图片时,首先会检查要获取的图片缓存中是否存在,若存在,直接取出来,不需要再去网络上获取。

小结:
1. SoftReference:软引用–>当虚拟机内存不足时,将会回收它指向的对象;需要获取对象时,可以调用get方法
2. WeakReference:弱引用–>随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收。要获取对象时,同样可以调用get方法。
参考:Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
WeakReference 在android中的应用

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐