0

I have the following fragment which loads a lot of data , this fragment has an inner static class which extends AsyncTask in the following way with weak reference to the fragment itself to prevent memory leaks:

public class PokemonDescriptionFragment extends Fragment {

////////Code

   private static class LoadPokemonData extends AsyncTask<Void, Void, Pokemon> {

    private WeakReference<PokemonDescriptionFragment> appReference;//FIXME Should I pass fragment as weak reference?

    LoadPokemonData(PokemonDescriptionFragment context) {
        appReference = new WeakReference<>(context);
    }

    /**
     * Executed before starting the BACKGROUND THREAD
     * Executed in the MAIN THREAD
     */
    @Override
    protected void onPreExecute() {
        final PokemonDescriptionFragment fragment = appReference.get();
        if (fragment == null) return;
        GenericUtils.changeVisibility(View.VISIBLE, fragment.pokedexDataProgressBar, fragment.biologyProgressBar, fragment.statsDataProgressBar, fragment.abilitiesProgressBar, fragment.etymologyProgressBar);
        GenericUtils.changeVisibility(View.GONE, fragment.llPokedexContainer);
    }

    /**
     * Executes after onPreExecute.
     * Is executed in the BACKGROUND THREAD
     * Here you can call "publishProgress" method that executes the "onProgressUpdate" method in Main thread ,
     * however , in this case , as I use indeterminated progress bar isn't necessary
     *
     * @return its sends the values to "onPostExecute"
     */
    @Override
    protected Pokemon doInBackground(Void... params) {
        final PokemonDescriptionFragment fragment = appReference.get();
        if (fragment == null) return null;
        fragment.initializePokemonData();
        return fragment.selectedPokemon;
    }

    /**
     * Executes after doInBackground
     * Executed in the MAIN THREAD
     */
    @Override
    protected void onPostExecute(Pokemon pokemon) {

        final PokemonDescriptionFragment fragment = appReference.get();
        if (fragment == null) return;
        if (Objects.nonNull(pokemon)) {
            MainActivity.setSelectedPokemon(pokemon);
            fragment.abilityAdapter.refreshAbilities(fragment.abilityList);
        }
        GenericUtils.changeVisibility(View.GONE, fragment.pokedexDataProgressBar, fragment.biologyProgressBar, fragment.statsDataProgressBar, fragment.abilitiesProgressBar, fragment.etymologyProgressBar);
        GenericUtils.changeVisibility(View.VISIBLE, fragment.llPokedexContainer);
        fragment.displayFullData();
    }

}

However , im not sure if this is 100% safe , I pass the fragment as weak reference because I need to access to some methods and attributes that the fragment has .Also , if you check my code I declare 3 times :

  final PokemonDescriptionFragment fragment = appReference.get();
    if (fragment == null) return null;

In the async task instead of declaring it as a global attribute of async task and referencing it in the 3 methods , is this correct ? Is there any problem if I add it as a global attribute of Asny task?

Nexussim Lements
  • 535
  • 1
  • 15
  • 47

1 Answers1

0

Adding the Fragment as a WeakReference in an AsyncTask is safe and shouldn't be an issue in terms of memory leaks.

Also, its a good idea to cancel the AsyncTask in your Fragments onDestroy() to not waste resources.

But consider refactoring your code entirely, for a better architecture that prevents the need of the Fragment context in AsyncTask entirely.

Tal Mantelmakher
  • 994
  • 1
  • 7
  • 23