Key*_*vat 232 android android-asynctask android-runonuithread
我在我的代码中收到警告:
这个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();
Run Code Online (Sandbox Code Playgroud)
我该如何纠正?
Sur*_*gch 513
为了防止泄漏,可以使内部类静态.但问题是,您无法再访问Activity的UI视图或成员变量.你可以传入一个引用,Context但是你会遇到内存泄漏的相同风险.(如果AsyncTask类具有强引用,则Android关闭后不能对Activity进行垃圾收集.)解决方案是对Activity(或任何Context你需要的)进行弱引用.
public class MyActivity extends AppCompatActivity {
int mSomeMemberVariable = 123;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// start the AsyncTask, passing the Activity context
// in to a custom constructor
new MyTask(this).execute();
}
private static class MyTask extends AsyncTask<Void, Void, String> {
private WeakReference<MyActivity> activityReference;
// only retain a weak reference to the activity
MyTask(MyActivity context) {
activityReference = new WeakReference<>(context);
}
@Override
protected String doInBackground(Void... params) {
// do some long running task...
return "task finished";
}
@Override
protected void onPostExecute(String result) {
// get a reference to the activity if it is still there
MyActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;
// modify the activity's UI
TextView textView = activity.findViewById(R.id.textview);
textView.setText(result);
// access Activity member variables
activity.mSomeMemberVariable = 321;
}
}
}
Run Code Online (Sandbox Code Playgroud)
AsyncTask教程仍然没有处理它(见这里,这里,这里,这里).AsyncTask是顶级课程,您也会遵循类似的程序.静态内部类与Java中的顶级类基本相同.如果您不需要Activity本身但仍需要Context(例如,显示a Toast),则可以传入对应用程序上下文的引用.在这种情况下,AsyncTask构造函数看起来像这样:
private WeakReference<Application> appReference;
MyTask(Application context) {
appReference = new WeakReference<>(context);
}
Run Code Online (Sandbox Code Playgroud)Ana*_*and 56
非静态内部类包含对包含类的引用.当您声明AsyncTask为内部类时,它可能比包含Activity类更长寿.这是因为对包含类的隐式引用.这将防止活动被垃圾收集,从而导致内存泄漏.
要解决您的问题,请使用静态嵌套类而不是匿名,本地和内部类,或使用顶级类.
Pha*_*inh 21
此类AsyncTask应该是静态的,否则可能会发生泄漏
Activity被摧毁,AsyncTask(两个static或non-static)仍在运行non-static(AsyncTask)类,它将引用外部类(Activity).Garbage Collected将释放它.如果一个对象未使用且Garbage Collected 无法释放它=>泄漏内存=>如果AsyncTask是non-static,Activity将不会释放它被销毁的事件=>泄漏
将AsyncTask作为静态类而不泄漏后的更新UI解决方案
1)使用WeakReference@Suragch回答
2)发送和删除Activity对(from)的引用AsyncTask
public class NoLeakAsyncTaskActivity extends AppCompatActivity {
private ExampleAsyncTask asyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// START AsyncTask
asyncTask = new ExampleAsyncTask();
asyncTask.setListener(new ExampleAsyncTask.ExampleAsyncTaskListener() {
@Override
public void onExampleAsyncTaskFinished(Integer value) {
// update UI in Activity here
}
});
asyncTask.execute();
}
@Override
protected void onDestroy() {
asyncTask.setListener(null); // PREVENT LEAK AFTER ACTIVITY DESTROYED
super.onDestroy();
}
static class ExampleAsyncTask extends AsyncTask<Void, Void, Integer> {
private ExampleAsyncTaskListener listener;
@Override
protected Integer doInBackground(Void... voids) {
...
return null;
}
@Override
protected void onPostExecute(Integer value) {
super.onPostExecute(value);
if (listener != null) {
listener.onExampleAsyncTaskFinished(value);
}
}
public void setListener(ExampleAsyncTaskListener listener) {
this.listener = listener;
}
public interface ExampleAsyncTaskListener {
void onExampleAsyncTaskFinished(Integer value);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
73688 次 |
| 最近记录: |