如何防止加载器在屏幕方向更改期间重新启动? - Android

时间:2018-04-17 18:53:04

标签: android loader screen-orientation

我有一个活动,在RecyclerView中显示食谱列表。项目的计算成本很高,因此我使用加载程序填充RecyclerView,并且该加载程序缓存数据以防止它重复计算。

当我在显示配方列表后旋转屏幕时,它表现良好(即不重复计算)。但是当我在> 计算期间旋转屏幕时,加载程序从头开始再次开始计算(例如,如果我每5秒旋转一次屏幕,它就不会显示任何内容,因为计算大约需要12个秒)。此外,如果我点击食谱,启动一个新活动,然后旋转屏幕,然后单击返回我的食谱列表活动,加载程序再次开始计算所有内容。

这是应用程序的可接受行为吗?如何防止这些重复计算发生?

我的onCreate使用此行的加载器:

getSupportLoaderManager().initLoader(RECIPES_LOADER_ID, null, this);

我的活动以这种方式覆盖了加载程序回调:

@NonNull
@Override
public Loader<List<Recipe>> onCreateLoader(int id, @Nullable Bundle args) {
    return new RecipesLoader(this, /* other parameters here */);
}

@Override
public void onLoadFinished(@NonNull Loader<List<Recipe>> loader, List<Recipe> data) {
    inventingTextView.setVisibility(View.INVISIBLE);
    inventingProgressBar.setVisibility(View.INVISIBLE);
    if (data != null) {
        recipesAdapter.updateRecipes(data);
    }
}

@Override
public void onLoaderReset(@NonNull Loader<List<Recipe>> loader) {
    recipesAdapter.updateRecipes(null);
}

My RecipesLoader是我的活动中的静态嵌套类:

private static class RecipesLoader extends AsyncTaskLoader<List<Recipe>> {

    private List<Recipe> recipes = null;
    private /* other member variables here */

    public RecipesLoader(@NonNull Context context, /* other parameters here */) {
        super(context);
        /* initializing member variables here */;
    }

    @Override
    protected void onStartLoading() {
        super.onStartLoading();
        if (recipes != null) {
            deliverResult(recipes);
        } else {
            forceLoad();
        }
    }

    @Nullable
    @Override
    public List<Recipe> loadInBackground() {
        return /* costly computation here */
    }

    @Override
    public void deliverResult(@Nullable List<Recipe> data) {
        recipes = data;
        super.deliverResult(data);
    }
}

2 个答案:

答案 0 :(得分:0)

首先,请考虑检测用户何时到达列表末尾然后联系服务器,以便降低整体装载成本。

无论如何,这是可能的解决方案:

<强> MainActivity

public class MainActivity extends Activity {

    private List<Recipe> recipes;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        // initialize layout here

        restoreState(savedInstanceState);   
    }

    public void restoreState(Bundle state) {
        if(state == null) {
            // this is the first time activity is created
            recipes = new RecipesLoader().loadInBackground();
        }else {
            // configuration has been changed (e.g. device rotated)
            recipes = state.getSerializable("recipes");     
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle stateToSave) {
        super.onSaveInstanceState(stateToSave);

        stateToSave.putSerializable("recipes", recipes);
    }
}

<强>配方

public class Recipe implements Serializable {
    // must implement Serializable because it will be passed through Intent

    . . .
}

顺便说一句,你可以看看第34章“繁忙的编码器Android开发指南”中的第19章。这解释了如何处理轮换变化。

答案 1 :(得分:0)

对于该活动在android Menifest文件中设置android:configChanges=orientation