rub*_*ees 13 android kotlin android-architecture-components android-paging
我目前正在考虑将Paging Architecture库(2.1.0-beta01编写本文时的版本)整合到我的应用程序中.一个组件是允许用户从中删除单个项目的列表.此列表仅限网络,并且使用Room缓存localy没有意义.
PagedList是不可变的,不支持修改.我已经读过有一个列表的副本,该列表被修改并返回,因为新的列表是要走的路.文档说明了相同的内容:
如果您有更精细的更新信号,例如网络API发信号通知对列表中单个项目的更新,则建议将数据从网络加载到内存中.然后通过包装内存中快照的DataSource将该数据呈现给PagedList.每次内存中副本更改时,都会使先前的DataSource无效,并且可以创建包装快照新状态的新数据.
我目前有基本推荐的实现来显示一个简单的列表.我DataSource看起来像这样:
class MyDataSource<SomeItem> : PageKeyedDataSource<Int, SomeItem>() {
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, SomeItem>) {
// Simple load from API and notification of `callback`.
}
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, SomeItem>) {
// Simple load from API and notification of `callback`.
}
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, SomeItem>) {
// Simple load from API and notification of `callback`.
}
}
Run Code Online (Sandbox Code Playgroud)
如何在文档中引用的内存缓存(没有Room并且没有使整个数据集无效)的具体实现如何?
如果你想修改你的列表而不一直到数据层,你需要submitList在你的适配器中覆盖,然后在你的PagedList对象上设置一个回调。每当PagedList发生更改时,您都可以将这些更改复制到本地数据集。不推荐这样做,但这是一个非常小的工作。
下面是一个例子:
class MyListAdapter : PagedListAdapter<MyDataItem, MyViewHolder>(MyDiffCallback()) {
/**
* This data set is a bit of a hack -- we are copying everything the PagedList loads into our
* own list. That way we can modify it. The docs say you should go all the way down to the
* data source, modify it there, and then bubble back up, but I don't think that will actually
* work for us when the changes are coming from the UI itself.
*/
private val dataSet = arrayListOf<MyDataItem>()
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
//Forces the next page to load when we reach the bottom of the list
getItem(position)
dataSet.getOrNull(position)?.let {
holder.populateFrom(it)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = parent.inflate(R.layout.my_view_holder)
return MyViewHolder(view)
}
class MyDiffCallback : DiffUtil.ItemCallback<MyDataItem>() {
override fun areItemsTheSame(oldItem: MyDataItem, newItem: MyDataItem) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: MyDataItem, newItem: MyDataItem) =
oldItem == newItem
}
override fun submitList(pagedList: PagedList<MyDataItem>?) {
pagedList?.addWeakCallback(listOf(), object : PagedList.Callback() {
override fun onChanged(position: Int, count: Int) {
dataSet.clear()
dataSet.addAll(pagedList)
}
override fun onInserted(position: Int, count: Int) {
dataSet.clear()
dataSet.addAll(pagedList)
}
override fun onRemoved(position: Int, count: Int) {
dataSet.clear()
dataSet.addAll(pagedList)
}
})
super.submitList(pagedList)
}
}
Run Code Online (Sandbox Code Playgroud)
您是正确的, aDataSource旨在保存不可变数据。我相信这是因为 Room 和 Paging Library 正在尝试做出更加固执己见的设计决策并倡导不可变数据。
这就是为什么在官方文档中,他们有一个用于更新或改变数据集的部分,当发生此类更改时,应该使数据源无效。
更新分页数据:如果您有更细粒度的更新信号,例如网络 API 发出对列表中单个项目的更新信号,建议将数据从网络加载到内存中。然后通过包装内存快照的 DataSource 将该数据呈现给 PagedList。每次内存中副本发生更改时,都会使先前的 DataSource 失效,并且可以创建一个包装快照新状态的新 DataSource。
来源: https: //developer.android.com/reference/android/arch/paging/DataSource
考虑到这一点,我相信可以通过几个步骤解决您所描述的问题。
这可能不是最干净的方法,因为它涉及两个步骤。
您可以获取 PagedList 所持有的快照的引用,该快照是一种 type MutableList。然后,您可以仅删除或更新该快照内的项目,而无需使数据源失效。
然后第二步是调用类似notifyItemRemoved(index)or 的东西notifyItemChanged(index)。
由于您无法强制数据源将更改通知观察者,因此您必须手动执行此操作。
pagedList.snapshot().remove(index) // Removes item from the pagedList
adapter.notifyItemRemoved(index) // Triggers recyclerview to redraw/rebind to account for the deleted item.
Run Code Online (Sandbox Code Playgroud)
也许在您的DataSource.Factory. 根据官方文档,一旦数据更新,您DataSource.Factory应该是发出新数据的人。PagedList
更新分页数据:要从提供更新的源分页数据,您可以创建一个 DataSource.Factory,当数据集发生更新导致当前快照无效时,创建的每个 DataSource 都会失效。例如,当从数据库中分页查询时,正在查询的表会插入或删除项目。您还可以使用 DataSource.Factory 提供多个版本的网络分页列表。如果需要重新加载所有内容(例如,响应滑动刷新等操作)才能获取新版本的数据,您可以连接显式刷新信号以在当前数据源上调用 invalidate() 。
来源: https: //developer.android.com/reference/android/arch/paging/DataSource
然而,我还没有找到第二种方法的良好解决方案。
| 归档时间: |
|
| 查看次数: |
3075 次 |
| 最近记录: |