简体   繁体   English

如何防止Loader在屏幕方向更改期间重新启动? -安卓

[英]How to prevent Loader from restarting during screen orientation change? - Android

I have an activity that presents a list of recipes in a RecyclerView. 我有一个活动,在RecyclerView中显示食谱列表。 The computation of the items is costly, so I use a loader to populate the RecyclerView and that loader caches the data to prevent it from repeating the computation. 项目的计算成本很高,因此我使用加载程序填充RecyclerView,并且该加载程序缓存数据以防止其重复计算。

When I rotate the screen after the list of recipes is shown it behaves well (ie does not repeat the computation). 显示配方列表后旋转屏幕时,它表现良好(即不重复计算)。 But when i rotate the screen during the computation the loader starts computing again from beginning (so, eg, if i am rotating the screen every 5 seconds it never gets to show anything, because the computation takes about 12 seconds). 但是,当我计算过程中旋转屏幕 ,加载程序会从头开始重新进行计算(因此,例如,如果我每5秒钟旋转一次屏幕,它将永远不会显示任何内容,因为计算大约需要12秒钟)。 Also, if i click on a recipe, launching a new activity, then rotate the screen and then click to go back to my recipe list activity, the loader starts computing everything again. 另外,如果我单击一个食谱,启动一个新活动,然后旋转屏幕,然后单击以返回到我的食谱列表活动,则加载程序将再次开始计算所有内容。

Is this an accepted behavior for an app? 这是应用程序的可接受行为吗? How can i prevent these repeated computations from happening? 如何防止这些重复的计算发生?

My onCreate uses the loader with this line: 我的onCreate在此行中使用加载程序:

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

My activity overrides the loader callbacks this way: 我的活动以这种方式覆盖了加载程序回调:

@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 is a static nested class inside my activity: 我的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);
    }
}

First of all, please consider detecting when user reaches the end of the list and then contact the server so the overall loading cost will be decreased. 首先,请考虑检测用户何时到达列表的末尾,然后与服务器联系,以降低总体加载成本。

Anyway, here is the possible solution: 无论如何,这是可能的解决方案:

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

Recipe 食谱

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

    . . .
}

By the way, you can take a look at chapter 19 in "The Busy Coder's Guide to Android Development" that explains how to handle rotation changes. 顺便说一句,您可以看一下“忙于Android开发的编码员指南”中的第19章,其中介绍了如何处理旋转更改。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在方向更改期间阻止应用重新启动 - Prevent app from restarting during orientation change 如何防止由于方向改变而重启? - How to prevent restarting from orientation change? Android-如何防止ViewPager的加载程序在配置更改时重新启动? - Android - How to prevent ViewPager's Loader restarting on configuration change? 如何防止方向更改期间活动重新开始? - How to prevent activity from restart during orientation change? 如何在自动化测试期间更改屏幕方向? - How to change the screen orientation during automated testing? Android:如何防止方向更改后重新加载活动? - Android: How to prevent activity from reloading after orientation change? Android:如何防止广播因方向改变而丢失? - Android: How to prevent Broadcast from being lost on orientation change? 如何从Android中的服务更改设备的屏幕方向? - How to change a device's screen orientation from service in android? Android:手动屏幕方向而不重新启动活动? - Android: manual screen orientation without restarting the activity? 如何在方向更改(嵌套片段)期间防止重新加载Android WebView? - How do I prevent the reload of an Android WebView during an orientation change (nested fragments)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM