我在我的代码中收到警告:
此AsyncTask类应该是静态的,否则可能会发生泄漏(匿名android.os.AsyncTask)
完整的警告是:
此AsyncTask类应该是静态的或可能发生泄漏(匿名android.os.AsyncTask)静态字段将泄漏上下文 . 非静态内部类具有对其外部类的隐式引用 . 如果该外部类例如是片段或活动,则此引用意味着长时间运行的处理程序/加载器/任务将保留对活动的引用,从而阻止其收集垃圾 . 同样,对来自这些较长时间运行的实例的活动和片段的直接字段引用可能会导致泄漏 . ViewModel类永远不应该指向视图或非应用程序上下文 .
这是我的代码:
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
return null;
}
}.execute();
我该如何纠正?
3 回答
非静态内部类包含对包含类的引用 . 当您将
AsyncTask
声明为内部类时,它可能比包含Activity
类的寿命更长 . 这是因为对包含类的隐式引用 . 这将防止活动被垃圾收集,从而导致内存泄漏 .要解决您的问题,请使用静态嵌套类而不是匿名,本地和内部类,或使用顶级类 .
如何使用静态内部AsyncTask类
为了防止泄漏,可以使内部类静态 . 但问题是,您无法再访问Activity的UI视图或成员变量 . 您可以传入对
Context
的引用,但之后会出现内存泄漏的相同风险 . (如果AsyncTask类具有强引用,则Android关闭后不能对Activity进行垃圾收集 . )解决方案是对Activity(或者你需要的任何Context
)进行弱引用 .注意事项
据我所知,这种类型的内存泄漏危险一直都是真的,但我才开始在Android Studio 3.0中看到警告 . 很多主要的
AsyncTask
教程仍然没有处理它(参见here,here,here和here) .如果您的
AsyncTask
是顶级课程,您也会遵循类似的程序 . 静态内部类与Java中的顶级类基本相同 .如果您不需要Activity本身但仍需要Context(例如,显示
Toast
),则可以传入对应用程序上下文的引用 . 在这种情况下,AsyncTask
构造函数将如下所示:有一些参数可以忽略这个警告而只是使用非静态类 . 毕竟,AsyncTask的使用寿命非常短(最长几秒),并且无论如何都会在活动结束时释放对Activity的引用 . 见this和this .
优秀文章:How to Leak a Context: Handlers & Inner Classes
This AsyncTask class should be static or leaks might occur because
当
Activity
被销毁时,AsyncTask
(static
或non-static
)仍然在运行如果内部类是
non-static
(AsyncTask
)类,它将引用外部类(Activity
) .如果对象没有引用指向它,
Garbage Collected
将释放它 . 如果一个对象未使用且Garbage Collected
can not 释放它=>泄漏内存=>如果
AsyncTask
是non-static
,Activity
将不会释放它被销毁的事件=>泄漏Solution for update UI after make AsyncTask as static class without leak
1)使用
WeakReference
喜欢@Suragch的答案2)发送和删除
Activity
引用(来自)AsyncTask