AsyncTask,如何在所有UI方法中正确使用WeakReference

时间:2018-03-11 06:54:56

标签: android android-asynctask weak-references

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

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

2 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:0)

在这里使用弱引用的最正确,最明显的方法是不这样做。相反,您应在活动被销毁时取消任务。这样可以防止内存泄漏,并停止无用的异步计算。

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