自定义无内存泄漏的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();

这样我们就能彻底避免内存泄露啦!
所以综上所述,只有做到这“三重”防护,我们才算是真正做到避免了内存泄漏☺。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值