方向更改后,WeakReference不断返回活动参考

时间:2018-03-11 12:10:57

标签: java android android-asynctask garbage-collection weak-references

我想在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();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

当活动被销毁时,活动对象应该有资格进行垃圾回收。这意味着,某些下一个GC事件将释放活动的内存保留。

您正在做出一个假设,即GC必须在您执行方向更改后立即发生,但事实并非如此。 WeakReference确保的是,下次GC尝试清理内存时保留对象不是理由。活动对象迟早会被GC清除,但不会像你期望的那样立即发生。

您可以使用System.gc()来启动同步GC事件,但不建议在正常情况下依赖此方法。


    System.gc();
    MainActivity activity = activityReference.get();
    // now `activity` should be null