Android 我应该在异步任务中将片段作为弱引用传递吗?

Posted

技术标签:

【中文标题】Android 我应该在异步任务中将片段作为弱引用传递吗?【英文标题】:Android should I pass fragment as weak reference in async task? 【发布时间】:2020-12-10 16:20:39 【问题描述】:

我有以下加载大量数据的片段,这个片段有一个内部静态类,它以以下方式扩展 AsyncTask 并弱引用片段本身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();
    


但是,我不确定这是否 100% 安全,我将片段作为弱引用传递,因为我需要访问片段具有的一些方法和属性。此外,如果您检查我的代码,我声明了 3 次:

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

在异步任务中,而不是将其声明为异步任务的全局属性并在3种方法中引用它,这是正确的吗?如果我将它添加为 Asny 任务的全局属性有什么问题吗?

【问题讨论】:

【参考方案1】:

AsyncTask 中添加Fragment 作为WeakReference 是安全的,不应该成为内存泄漏问题。

另外,最好取消片段中的AsyncTask onDestroy(),以免浪费资源。

但请考虑完全重构您的代码,以获得更好的architecture,从而完全避免在 AsyncTask 中需要 Fragment 上下文。

【讨论】:

以上是关于Android 我应该在异步任务中将片段作为弱引用传递吗?的主要内容,如果未能解决你的问题,请参考以下文章

我应该在 Fragment 中的啥生命周期状态下执行异步任务?

Android:正确停止异步任务

屏幕方向期间片段内的异步任务

异步任务类完成后如何更改文本视图的值(在片段中)?

java 登录过程 - android片段,异步任务登录,Asp.net控制器,存储库

片段作为 Android 中的单例