你试过弱引用弱爆了吗?原因竟然是 ... ...

本文探讨了Android开发中使用弱引用(WeakReference)可能遇到的问题,特别是在内存回收时导致的回调方法未被调用的情况,并提供了解决方案。

Android WeakReference 带来的问题


背景

其实开始的时候本人也像很多人一样,因为Handler出现的内存泄露问题,因此开始使用起weakReference的,还信心满满的以为,从此我和我的小伙伴再也不担心内存泄露。

然而,其实weakReference真的那么好?来看代码吧,我们常规时候定义一个自定义的Handler来异步请求处理代码,当然LZ表示自己是个很懒得人,因此自己写了个BaseHandler通过反射直接执行回调方法,这个先不说。


public static class MyHandler extends Handler{
         private WeakReference<MyActivity> wActivity;
         
         public MyHandler(MyActivity activity){
               wActivity = new WeakReference(activity);
         }    

         void handleMessage(Message msg){
               //do something
               MyActivity myActivity = wActivity .get();
               if(myActivity !=null){
                      myActivity.doSomething();
               }
         }
}

这是我们常规写的,那么有啥问题?这似乎木有问题啊,恩,LZ当初也是这样想的,直到一天我手贱的时候。 大家都知道,Java垃圾回收机制对吧。知道的话应该知道LZ接下来说的问题,对当内存不足的时候WeakReference会被回收的,但是有个问题是当前Activity还在活动的时候WeakReference是否还是会被回收? ...答案肯定的 一样回收!!!。因此你想过木有突然出发内存回收,那么你本来要回调的方法,呵呵呵呵呵呵.....那么怎么会触发他回收,我做的很简单,那时因为Activity前面已经有很长的Activity栈,而且LZ很无耻的不停来回切换一个不是singleTask或者singleTop的Activity。然后某一次,有个回调方法没调用....看如下测试代码(这个是我之前写一篇文章 Android MVVM使用经验篇中一段代码):

public class AdapterModule<T> {
    // not use onClick
    public static final int BINDVAIABLE_NONE = 0;

    public ObservableArrayList<T> list = new ObservableArrayList<>();
    // bindingVaiable id
    public ObservableInt bindingVaiable;
    // bind PositionId
    public ObservableInt bindPositionVaiableId;
    // the key is the resourceId!
    public WeakReference<SparseArray<OnClickListener>> listeners;
    // manual notify
    public boolean manualNotify = false;

    //代码省略
}


 @Override
    public BindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (inflater == null) {
            inflater = LayoutInflater.from(parent.getContext());
        }

        ViewDataBinding binding = DataBindingUtil.inflate(inflater, layoutId.get(), null, false);
        final BindingHolder holder = new BindingHolder(binding, (SparseArray<OnClickListener>) adapterModule.listeners.get());

       ///代码省略
        return holder;
    }

public static class BindingHolder<T> extends RecyclerView.ViewHolder {

        ViewDataBinding binding;
        private SparseArray<OnClickListener> listeners;

        public BindingHolder(ViewDataBinding binding, SparseArray<OnClickListener> listeners) {
            super(binding.getRoot());
            this.binding = binding;
            this.listeners = listeners;
            Log.e("textListener is null?", (listeners == null) + "");
            onBindListeners();
        }

        public void onBindListeners() {
            if (listeners != null && listeners.size() > 0) {
                for (int i = 0; i < listeners.size(); i++) {
                    binding.setVariable(listeners.keyAt(i), listeners.get(listeners.keyAt(i)));
                }
            }
        }
    }




最后在我来回切换页面时候有以下输出:
....前面省略N个。
09-28 21:48:39.859 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:39.866 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:39.873 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:40.925 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:40.932 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:40.940 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:41.975 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:41.983 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:41.990 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:42.958 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:42.964 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:42.970 14872-14872/com.ykse.ticket E/textListener is null?: false
09-28 21:48:44.074 14872-14872/com.ykse.ticket E/textListener is null?: true
09-28 21:48:44.081 14872-14872/com.ykse.ticket E/textListener is null?: true
09-28 21:48:44.091 14872-14872/com.ykse.ticket E/textListener is null?: true

看到木有-。-或许前面有N个没事,但是某一个时刻,哼哼,说了那么多怎么解决,其实也很简单。。。不用WeakReference呗,然后在相关Activity或者Fragment或者View detach时候将Activity引用去掉就行了呗~当然如果你非要说道线程不安全-。-要加同步锁,我不反对~~看代码


public static class MyHandler extends Handler{
         private MyActivity activity;
         
         public MyHandler(MyActivity activity){
               this.activity= activity;
         }    

         void handleMessage(Message msg){
               //do something
               if(myActivity !=null){
                      myActivity.doSomething();
               }
         }
         
         public synchronized void destory(){
                   myActivity = null;
         }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值