自定义无内存泄漏的Handler内部类
Posted 碎格子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义无内存泄漏的Handler内部类相关的知识,希望对你有一定的参考价值。
最近做项目有很多需要在子线程中进行耗时操作,因为操作也比较简单,也就是单纯的发送网络请求然后处理回调更新UI,所以选择了Thread+Runnable+Handler的组合。
然后有了最初的代码:
代码片段1:SGAddressFragment.java
Handler handler;
public void onActivityCreated(@Nullable Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
if (getView() != null)
...
handler = new Handler()
@Override
public void handleMessage(Message msg)
updateView();
super.handleMessage(msg);
;
private void saveNewAddress()
saveNewThread = new Thread(new Runnable()
@Override
public void run()
Message msg = new Message();
Bundle bundle = new Bundle();
try
boolean isSaved = doSaveNewAddress();
bundle.putBoolean("boolean_save", isSaved);
catch (Exception e)
e.printStackTrace();
msg.setData(bundle);
handler.sendMessage(msg);
);
saveNewThread.start();
threads.add(saveNewThread);
其实很多人可能一不小心就会写出这样的代码,好在android Studio检测出来了这样的情况,并且给出了警告:
Android Studio自己检查出来可能出现内存泄漏,然后他推荐我们使用静态类来避免。为什么一定要是静态内部类?这里应该很多人都知道,非静态内部类会持有外部类的引用,而静态内部类则不会有这样的情况。具体原因可以参考这篇文章。那么我们就照它所推荐的方法,将Handler改造成静态内部类:
代码片段2:
static class AddressHandler extends Handler
WeakReference<SGAddressFragment> sgAddressFragmentRef;
AddressHandler(SGAddressFragment sgAddressFragment)
sgAddressFragmentRef = new WeakReference<>(sgAddressFragment);
@Override
public void handleMessage(Message msg)
boolean b;
if (msg.getData() != null)
sgAddressFragmentRef.get().update();
super.handleMessage(msg);
以上就将我们的Handler改造成了静态的内部类。这里由于更新要用到外部类Fragment里的非静态方法,所以将一个Fragment对象传进来,而大家可以看到,我使用了WeakReference对传入的对象进行弱引用处理,我们可以借助弱引用类型对外部非静态变量进行操作,而Handler仅有一条弱引用指向了Fragment对象,所以不会影响Fragment的回收,使用WeakReference也是避免内存泄漏很重要的一点。
还有一点不得不说,眼尖的朋友可以看到,在代码片段1里,当我start了线程之后,有这样一段代码:threads.add(saveNewThread);
而这段代码在内存泄漏处理中也起到了非常大的作用。当我们新开一个线程,如果这个线程的工作一直到Activity被finish掉也没有处理完,那它将一直持有这个Activity导致Activity不能被回收。所以我在代码中创建了一个ArrayList对象用来存入新开的线程:ArrayList<Thread> threads = new ArrayList<>();
每当我们新开了线程之后,就将thread对象添加进list里:threads.add(saveNewThread);
然后在onDestroy()方法里将所有添加进去的线程中断:
for (Thread thread : threads)
if (thread != null && thread.isAlive())
thread.interrupt();
threads.clear();
这样我们就能彻底避免内存泄露啦!
所以综上所述,只有做到这“三重”防护,我们才算是真正做到避免了内存泄漏☺。
以上是关于自定义无内存泄漏的Handler内部类的主要内容,如果未能解决你的问题,请参考以下文章