我想在AsyncTask中使用WeakReference来不泄漏内存。使用我可以看到的日志语句,如果我将活动留在后退按钮上,那么我从get
方法返回的活动引用确实为null。
但是,当我旋转设备时,我得到一个工作参考,这意味着我泄漏了内存。知道为什么会这样吗?
更新:一旦我离开活动,它就会在旋转设备后立即显示为空,然后打开另一个应用程序。可能是因为我的活动很简单,系统根本没有看到清理的必要性吗?
public class MainActivity extends AppCompatActivity {
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progress_bar);
}
public void startAsyncTask(View v) {
ExampleAsyncTask exampleAsyncTask = new ExampleAsyncTask(this);
exampleAsyncTask.execute(210);
}
private static class ExampleAsyncTask extends AsyncTask<Integer, Integer, String> {
private WeakReference<MainActivity> activityReference;
ExampleAsyncTask(MainActivity context) {
activityReference = new WeakReference<>(context);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
activity.progressBar.setVisibility(View.VISIBLE);
}
@Override
protected String doInBackground(Integer... integers) {
for (int i = 0; i < integers[0]; i++) {
publishProgress((i * 100) / integers[0]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Finished";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
Log.i("activity", "activity = null");
return;
} else
Log.i("activity", "activity not null");
activity.progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
activity.progressBar.setProgress(0);
activity.progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
}
}
}
答案 0 :(得分:1)
当活动被销毁时,活动对象应该有资格进行垃圾回收。这意味着,某些下一个GC事件将释放活动的内存保留。
您正在做出一个假设,即GC必须在您执行方向更改后立即发生,但事实并非如此。 WeakReference
确保的是,下次GC尝试清理内存时保留对象不是理由。活动对象迟早会被GC清除,但不会像你期望的那样立即发生。
您可以使用System.gc()
来启动同步GC事件,但不建议在正常情况下依赖此方法。
System.gc();
MainActivity activity = activityReference.get();
// now `activity` should be null