Search code examples
androidandroid-asynctaskweak-references

Can the strong reference returned from WeakReference's get method cause a memory leak in AsyncTask onProgressUpdate?


I want to use WeakReference to avoid a memory leak in AsyncTask. The examples I find online only use the get() method in onPostExecute, but I also want to use it to update the progress. Now I wonder if that very frequent call of the get method can in itself cause a memory leak?

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 (activityReference.get() == null) {
            return;
        }

        activity.progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    protected String doInBackground(Integer... integers) {
        Log.i("TAG", "doInBackground started");
        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();
    }
}

Solution

  • Your code almost has no strong reference as far as the get and onProgressUpdate are concerned because you are using local variable which will go out of scope, the moment onProgressUpdate is finished.

    So basically everytime your code is accessing the reference, retrieved from get() method so it is safe. Although it would have been an issue, if you would have kept a reference, declared outside onProgressUpdate method