没有“最佳实践”AFAIK,但以下是您选择的简短摘要:
在用户滚动时查询 UI 线程
一般来说,在 UI 线程上执行查询通常是一种非常糟糕的做法。在 ListView 中这样做是一种罪过。
也就是说,有一些 ORM 库可以在 UI 线程上执行嵌套对象的延迟加载(例如 GreenDAO)。人们在具有 ListViews 的应用程序中使用这些库,其中一些甚至可以正常工作。
我强烈反对这种方法。
提前查询所有项目
正如@CommonsWare 所提到的,对于中小型集合,您只需将整个数据集加载到后台线程的内存中,然后将其绑定到 ListView。在加载数据时,您需要显示某种进度指示。
“小”和“中”的定义非常模糊,但我想说,如果你确定数据集不会超过几 MB,那么这种方法可以很好地工作。
这种方法的缺点是用户需要等待整个数据集被加载并绑定到 ListView。根据数据集的大小和数据库方案的复杂性,这可能需要一段时间。
最初查询预定义数量的项目,然后在用户滚动时执行其他查询
这是最复杂的方案,但在某些情况下是不可避免的(例如“无限列表”)。
这个想法是将一些预定义数量的项目放入 ListView,然后跟踪用户的交互以提供额外的项目。
例如,您可以先获取 100 个项目,然后在用户滚动到列表末尾时再获取 100 个。
此方案的优化是在用户到达列表末尾之前获取额外的项目(假设当他滚动浏览 50 个项目时)。这允许创建真正的“无限列表”行为。
请注意,如果您的集合非常大,您不仅需要注意在用户滚动时添加新项目,还要注意删除“以前的”项目以避免内存不足崩溃。
查询已显示项目的附加信息
有时您想在项目已经显示后执行一些额外的查询。
在这种情况下,只需在后台执行查询并将数据绑定到项目即可。
此任务的一个警告是,如果项目的视图被回收(默认情况下在 RecyclerView 中就是这种情况),那么当您的后台获取完成时,目标视图可能会显示完全不同的项目。将返回的数据绑定到这个 View 会出错。
处理此问题的一种方法是取消提取。然而,这在实践中很麻烦且容易出错。
更简单的方法是在发起查询时设置transientState标志,并在查询完成时清除它。