我有一个列表视图/回收视图。现在,我想为每个项目添加更多信息,这些信息可以根据项目值在数据库中找到。你们是怎么做到的?是吗?
为了获得最佳实践,我应该在后台线程中查询数据库吗?如果用户滚动速度很快,我应该取消查询吗?
最佳答案
没有“最佳实践”AFAIK,但以下是您选择的简短摘要:
用户滚动时对ui线程的查询
通常在ui线程上执行查询是一种非常糟糕的做法。在ListView中这样做是一种罪恶。
也就是说,有些orm库在ui线程(例如greendao)上执行嵌套对象的延迟加载。人们在有列表视图的应用程序中使用这些库,它甚至对其中的一些应用程序也能正常工作。
我强烈反对这种方法。
提前查询所有项目
正如@commonware所提到的,对于中小型集合,您只需将整个数据集加载到后台线程的内存中,然后将其绑定到listview。在加载数据时,需要显示某种进度指示。
“small”和“medium”的定义非常模糊,但我要说的是,如果您确定数据集不会大于少数mbs,那么这个方法可以很好地工作。
此方法的缺点是,用户需要等待整个数据集加载并绑定到listview。根据数据集的大小和数据库方案的复杂性,这可能需要一段时间。
最初查询预定义数量的项,然后在用户滚动时执行其他查询
这是所有方案中最复杂的方案,但在某些情况下是不可避免的(例如“无限列表”)。
其思想是在listview中获得一些预定义的条目数量,然后跟踪用户的交互以提供额外的条目。
例如,最初可以提取100个项,然后当用户滚动到列表的末尾时再提取100个项。
这个方案的一个优化是在用户到达列表末尾之前获取额外的项(比如当他滚动50个项时)。这允许创建一个真正的“无限列表”行为。
请注意,如果您的集合很大,您不仅需要在用户滚动时添加新项,还需要删除“上一个”项,以避免内存不足崩溃。
查询已显示项的附加信息
有时您希望在项目已显示后执行一些附加查询。
在这种情况下,只需在后台执行查询并将数据绑定到项。
此任务的一个警告是,如果项的视图被回收(默认情况下在recyclerview中是这样),那么当后台提取完成时,目标视图可能会显示完全不同的项。将返回的数据绑定到此视图将是一个错误。
处理此问题的一种方法是取消提取。然而,这在实践中是繁琐且容易出错的。
更简单的方法是在查询启动时设置transientState
标志,并在查询完成时清除它。