zoukankan      html  css  js  c++  java
  • WeakReference 在android中的应用

    转载(https://my.oschina.net/u/1177694/blog/523922

    首先我们来看一段代码

    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却无法回收的情况。(至于为什么强引用不能够被gc自动回收,而

    弱引用对象为什么会被gc回收,可以自行去google)。

    所以解决这个警告就有几种方法:

    一:将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;
                }
            }
        }
    }
    原创作品,转载请注明出处!
  • 相关阅读:
    在SharePoint 2010 中使用REST时提示:未能加载类型System.Data.Services.Providers.IDataServiceUpdateProvider的解决办法
    个人记录:判断用户组是否存在
    计算列收集
    SharePoint 备忘录(一)
    个人收藏学习SHarePoint比较不错的网站
    修改WINDOWS 2008 r2远程桌面账户登录限制
    Sharepoint 2010新体验之一基于Claims的全新验证机制
    基于SharePoint的单点登录的实现
    [转]这么教你一定能懂!用饮水机教你什么是RAID
    SharePoint随笔
  • 原文地址:https://www.cnblogs.com/yidijimao/p/6727735.html
Copyright © 2011-2022 走看看