然而,其实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?: false09-28 21:48:39.866 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:39.873 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:40.925 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:40.932 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:40.940 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:41.975 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:41.983 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:41.990 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:42.958 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:42.964 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:42.970 14872-14872/com.ykse.ticket E/textListener is null?: false09-28 21:48:44.074 14872-14872/com.ykse.ticket E/textListener is null?: true09-28 21:48:44.081 14872-14872/com.ykse.ticket E/textListener is null?: true09-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; } }
