Android实现弱引用AsyncTask,将内存泄漏置之度外。

AsyncTask可谓是在Android中隐藏很深,曾经叱咤风云的功夫级人物。它的存在让网络和UI的通信变得异常简单和轻松。AsyncTask使用上的简单也得以让很多开发者青睐。一般情况下,AsyncTask会作为内部类在Activity或者Fragment中实现,例如:

Android实现弱引用AsyncTask,将内存泄漏置之度外。_第1张图片

相信很多朋友都是这么玩的。但是这样写会不会有问题呢?答案是肯定的。

首先,我们知道Java语言是一种强类型,强引用的语言。在一个类中创建内部类时,内部类会默认对外部类持有引用。可以简单的理解为,外部类作为了一个寄托者将内部类绑定在了自己身上。我们知道Activity或者Fragment是有生命周期存在的。并且AsyncTask多用于处理耗时操作(数据库,IO读写,网络请求等等。。)此时,就会出现一个严重的问题:在Activity或者Fragment生命周期结束后,由于AsyncTask的耗时任务尚未完成,导致Activity或者Fragment无法释放资源。即发生我们经常所听到的 “内存泄漏”。

有朋友可能不明白了,为什么会产生内存泄漏呢?

我们上面提到,由于内部类和外部类的绑定关系,并且AsyncTask的耗时操作导致外部类资源不能被及时GC。Java中默认的引用持有都是强引用类型。例如我们直接new出来的对象。为了避免这些问题,Java还为我们提供了软引用,弱引用,无引用持有等等一些工具。弱引用和软引用的作用几乎相同。都是在资源紧缺的情况下被得以回收。

所以,解决这个问题的关键之处就在于不要对外部类持有强引用,或者将内部类定义成static类型,让其与外部类拥有相同的生命周期。此时有朋友可能一脸懵逼,为啥定义成static就可以了。哈哈,你想哇,static静态的内部类属于外部类的静态成员,当外部类初始化时它才会被初始化,同样,当外部类被释放时,它也会被同时释放。也就是内部类与外部类同生共死。但是使用static类型的同样需要我们将在asyncTask中使用的变量也声明为static,数量少的情况下还是可以接受的,但是很多的static情况下,容易让内存吃紧,GC频繁。所以,合适的解决方案就是使用弱引用来改变内部类对外部类的引用关系。

即我们可以自定义一个Weak形式的AsyncTask,让其持有外部类的弱引用:

Android实现弱引用AsyncTask,将内存泄漏置之度外。_第2张图片

可以看到上面我们定义了一个WeakAsyncTask类继承自AsyncTask。在类中我们使用WeakRefrences来弱引用外部Context。所以,当外部类需要释放时,会立刻被GC所回收。避免了内存泄漏的问题。

使用方式很简单:

Android实现弱引用AsyncTask,将内存泄漏置之度外。_第3张图片

ok,本篇博客讲解了AsyncTask作为内部类导致内存泄漏以及以及如何解决该问题,相信大家也有了深刻认识。有问题的可以给我留言咯~

你可能感兴趣的:(Android)