我应该在 onSaveInstanceState 中保留数据对象吗

Should I persist data objects in onSaveInstanceState

我在 android 应用程序中使用 greenDAO 来显示 RecyclerView 中的对象列表。我有一个 RecyclerView.Adapter 的子类,它包含一个对象列表,这些对象是 greenDAO 实体。

我在onCreate中所做的是:

  1. 为我的列表创建一个传递 null 的适配器实例。这只是为了让下面的 RecyclerView 知道适配器。
  2. 使用布局和适配器初始化 RecyclerView
  3. 调用一个使用 greenDAO 异步查询数据的方法,并在成功后使用实际的对象列表更新适配器,以便显示它们。

这是相关代码:

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ...

    mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
    mListAdapter = new MyRecyclerAdapter(null);
    mList.setHasFixedSize(true);
    mList.setLayoutManager(mLayoutManager);
    mList.setAdapter(mListAdapter);
    refreshItems();
}

public void refreshItems()
{
    AsyncSession asyncSession = ((App)getApplication()).getDaoSession().startAsyncSession();
    asyncSession.setListenerMainThread(new AsyncOperationListener()
    {
        @Override
        public void onAsyncOperationCompleted(final AsyncOperation operation)
        {
            if (operation.isCompletedSucessfully())
                mListAdapter.setItems((List<Item>) operation.getResult());
        }
    });

    asyncSession.loadAll(Item.class);
}

这很好用。现在我注意到,每次我旋转 activity 或从另一个 activity 返回时,当然会调用通过 greenDAO 查询数据库的方法。这很清楚,因为我正在从 onCreate.

调用该方法

我的问题是:最好的做法是像我现在做的那样(每次重新查询 DAO)还是我应该使我的对象可打包并保存我在 onSaveInstanceState 中的列表并恢复它在 onRestore 而不是重新查询 DAO?

你所做的是完全有效的,你不需要将查询的数据保存在onSaveInstanceState(),使用内存缓存,或任何其他优化(即使 GreenDAO 没有内部缓存)。

事实上,您完全正确,因为您异步执行查询 - GreenDAO 的创建者声称在大多数情况下查询可以在 UI 线程上执行(我发现很难同意)。

我还建议您在 onStart() 而不是 onCreate() 中执行数据查询。我个人认为 onCreate() 应该只用于您将在构造函数中执行的操作(例如字段初始化)。在 onStart() 中执行此查询的另一个原因是,如果用户离开您的应用程序很长时间然后返回,数据可能会过时(例如,由于 SyncAdapter 的后台同步)和你会想要刷新它。

您可能要添加的最后一块是 "data change notifications"。如果您查询和显示给用户的数据可以在没有用户交互的情况下发生变化(例如,由于 SyncAdapter 的后台同步),您将希望使用此机制。这个概念很简单 - Activity 注册有关 onCreate() 中数据更改的通知,如果收到通知,您将执行重新查询以确保用户看到最新数据。

我不能说以上都是"best practices",但它们是行之有效的好做法。

惰性列表:

正如@pskink 在他的评论中所建议的那样,您也可以使用 LazyList。但是请注意,它并没有消除对数据异步查询的需要。使用 LazyList 允许您像往常一样执行查询,但以按需方式将结果加载到内存中。如果您希望查询产生大量数据,这可能很有用。

然而,在我看来,只有在观察到实际性能问题时才应该优化代码。因此,除非您提前知道特定查询会产生数千个结果,否则我说您不需要 LazyList.