【问题标题】:AsyncTask, how to properly use WeakReference in all the UI methodsAsyncTask,如何在所有 UI 方法中正确使用 Wea​​kReference
【发布时间】:2018-03-11 06:54:56
【问题描述】:

我想使用WeakReference 方法来避免我的AsyncTask 泄漏内存。我在网上和 Stackoverflow 上找到了示例,但它们仅在 onPostExecute 中获得参考,我不确定如何在所有 3 种 UI 方法中正确使用它。 我目前的方法是这样的,但我不知道是否可以摆脱一些冗余。为什么我不能只在构造函数中调用activityReference.get(),然后只在每个 UI 方法中检查 null?为什么在线示例在使用WeakReference 之前调用get

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 = 1; i < integers[0]; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            publishProgress((i * 100) / integers[0]);
        }

        return "Finished";
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        MainActivity activity = activityReference.get();
        if (activity == null || activity.isFinishing()) {
            return;
        }

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

【问题讨论】:

    标签: android android-asynctask weak-references


    【解决方案1】:

    您可以在构造函数中对其进行初始化,并在所有方法中使用它。

    private static class ExampleAsyncTask extends AsyncTask<Integer, Integer, String>
    {
        private WeakReference<MainActivity> activityReference;
        MainActivity activity;
    
        ExampleAsyncTask(MainActivity context)
        {
            activityReference = new WeakReference<>(context);
            activity = activityReference.get();
        }
    
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
    
            if (activity == null || activity.isFinishing())
            {
                return;
            }
    
            activity.progressBar.setVisibility(View.VISIBLE);
        }
    
        @Override
        protected String doInBackground(Integer... integers)
        {
            if (activity == null)
                return null;
    
            for (int i = 1; i < integers[0]; i++)
            {
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
    
                publishProgress((i * 100) / integers[0]);
            }
    
            return "Finished";
        }
    
        @Override
        protected void onProgressUpdate(Integer... values)
        {
            super.onProgressUpdate(values);
    
            if (activity == null || activity.isFinishing())
            {
                return;
            }
    
            activity.progressBar.setProgress(values[0]);
        }
    
        @Override
        protected void onPostExecute(String s)
        {
            super.onPostExecute(s);
    
            if (activity == null || activity.isFinishing())
            {
                return;
            }
    
            activity.progressBar.setProgress(0);
            activity.progressBar.setVisibility(View.INVISIBLE);
            Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
        }
    }
    

    【讨论】:

    • 谢谢,这对我来说更有意义!
    • 嗯,我希望能得到第二意见,以确保
    • 实际上我认为get 返回了对该活动的强引用,如果我将其保留为成员,这将破坏 WeakReference 的目的。你不这么认为吗?
    • 没办法。它只保存引用(不是隐式/强引用),每当Activity 被销毁时,它将变为空。这就是使用WeakReference 的全部意义所在
    【解决方案2】:

    这里使用弱引用最正确和最明显的方法是不使用。相反,您应该在 Activity 被销毁时取消任务。这将防止内存泄漏并停止变得无用的异步计算。

    public final class SomeActivity extends Activity {
        private AsyncTask<?, ?, ?> runningTask;
        private void startTaskPlease() {
            if (runningTask != null) runningTask.cancel(true);
            runningTask = new ExampleAsyncTask(this);
            runningTask.execute();
        }
        @Override protected void onDestroy() {
            super.onDestroy();
            if (runningTask != null) runningTask.cancel(true);
        }
    }
    

    现在您的AsyncTask#doInBackground 应该是对中断友好的,但 UI 部分不应该介意弱引用和取消。

    public final class ExampleAsyncTask extends AsyncTask<whatever> {
        private final SomeActivity activity; // now this is OK! Thanks to cancellation
        public ExampleAsyncTask(SomeActivity activity) {
            this.activity = activity;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-02
      • 1970-01-01
      • 2012-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多