WeakReference的使用和在Android中的应用

先介绍下WeakReference

WeakReference在java中被称为弱引用,其父类为Reference,其兄弟还有强引用,软应用,虚引用.一般强引用指向的对象java虚拟机是
不会主动回收的(除非java虚拟机判断该引用对象不再使用了,例如在某个方法中的局部变量,引用会从方法栈出弹出),而弱引用不一样,其回
收时机是下一次java发生gc动作时(此时没有其他的强引用指向它,并且该强应用发生过使用,待会再做出说明).所以,弱引用可以做一些调配缓存,适用于一些消耗比较大的对象,可以提高程序的性能.需要注意的是,在调用weakreference的get方法时一定要做判空动作,否则很容易造成空指针异常.

WeakReference使用示例代码

写个pojo类型对象

   public class TV {

    private String price;

    private String band;

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getBand() {
        return band;
    }

    public void setBand(String band) {
        this.band = band;
    }

}

调用WeakReference

 public class Client {

    public static void main(String[] args) {
        TV tv = new TV();
        tv.setPrice("2000");
        tv.setBand("海尔");
        WeakReference<TV> reference = new WeakReference<TV>(tv);

        while (true) {
            if (reference.get() == null) {
                System.out.println("对象被回收了");
                break;
            }else {
                System.out.println("对象还存在");
            }
        }
    }
}

打印结果

对象还存在
对象还存在
对象还存在
对象还存在
对象还存在
对象还存在
对象还存在
对象还存在
对象被回收了

这里说明对象确实在一段时间后就被回收了.

假如这个TV对象被其它强引用引用了呢,试一下.代码修改一下,如下:

public class Client {

private static TV mTV;  

    public static void main(String[] args) {
        TV tv = new TV();
        mTV = tv;
        tv.setPrice("2000");
        tv.setBand("海尔");
        WeakReference<TV> reference = new WeakReference<TV>(tv);

        while (true) {
            if (reference.get() == null) {
                System.out.println("对象被回收了");
                break;
            }else {
                System.out.println("对象还存在");
            }
        }
    }
}

修改后,Log打印根本停不下来:

对象还存在
对象还存在
对象还存在
对象还存在
对象还存在
对象还存在
对象还存在
对象还存在

再修改下,假如没有其他的强引用指向它,这里tv本身就是一个强引用,再在while循环里面使用下这个tv对象试试看,代码修改如下:

public class Client {

    public static void main(String[] args) {
        TV tv = new TV();
        tv.setPrice("2000");
        tv.setBand("海尔");
        WeakReference<TV> reference = new WeakReference<TV>(tv);

        while (true) {
            System.out.println(tv.getPrice());
            if (reference.get() == null) {
                System.out.println("对象被回收了");
                break;
            }else {
                System.out.println("对象还存在");
            }
        }
    }
}

修改后,Log也同样根本停不下来:

对象还存在
2000
对象还存在
2000
对象还存在
2000
对象还存在
2000

所以这两个修改印证了刚刚的说法.

那么在Android中这个WeakReference哪里又可以用到呢?
我们经常在Android中用到一个类叫做Handler,这个是很熟悉的一个类,它具有发送消息,处理消息,主线程切换等功能.那么在java
中,我们也知道非静态内部类匿名的存在一个对外部类的引用.而我们经常把Handler定义在Activity中,这样就会导致handler中的消息
没处理或者没处理完,导致Activity被关闭无法得到有效的释放.假如在studio中这么使用,系统会提示你把handler定义成一个静态内部
类,这个说明Google也是不希望我们这么做的.

诸如下面的代码所示,会导致内存泄露:

    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     mHandler.postDelayed(new Runnable() {
    @Override
    public void run() {
      // and do something

    }
    },2000);
    finish();
    }

    private Handler mHandler =  new Handler(){

    @Override
    public void handleMessage(Message msg) {
      //do something......

    }
       };
    }

此时的MainActivity就得不到有效的回收

那么该怎么做呢?此时WeakReference就派上用场了,我们一样把Handler定义成成员变量,只不过是静态的,此时就不会含有匿名的
Activity引用了.但是handler中一般要处理Activity中的业务逻辑,所以需要一个weakreference弱引用指向他,用于调用Activity中
当前存在的逻辑方法.但是要注意,记得判空动作.

示例代码如下:

public class MainActivity extends Activity {

private TextView mTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView = (TextView) findViewById(R.id.tv_text);
}

private static class MyHandler extends Handler {
    private WeakReference<MainActivity> reference;

public MyHandler(MainActivity activity) {
    reference = new WeakReference<MainActivity>(activity);
}

@Override
public void handleMessage(Message msg) {
   //do something......
    MainActivity activity = reference.get();
    if(activity != null){
    activity.mTextView.setText("哈哈哈");
 }
  }
  }
}  

好了,关于WeakReference的讨论就到这里了,下篇写一篇关于WeakHashMap的讨论和实际应用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值