使用分页库更新单个元素的最佳方法

12

当使用新的分页库更新单个元素时,最好的方法是什么?

假设我们有一个谷歌示例Paging with network,使用PageKeyedSubredditDataSource。想象一下,我们想要更改RedditPost的一个单独元素。因此,我们想要检查它是否在列表中,如果是,则更新它。更新不应该像调用invalidate()那么容易,这将调用第一页(可能RedditPost在第5页)。我们只想更新一个元素,而不是所有元素。


1
如果您的数据源中的数据已更改,则可以通过调用 invalidate() 方法来更新它们,这将导致当前加载的所有页面无效,从而触发新数据的加载。此外,如果您想确保某些数据更新被立即应用于用户界面,则可以在数据源上调用 invalidate(),然后再次调用 loadAfter()loadBefore() 以重新获取数据。 - pskink
1
谢谢。但是有没有不使用内存的方法? - Damia Fuentes
1
我真的不明白为什么 room 到处都在使用 LiveData,但分页库需要固定数据或者我们需要实现某种内存 hacky 方式来使所有数据源失效。这里有什么解决方案吗?我的数据库一直在变化,因此会发出 liveData<TableEntry> 值,这对分页库来说并不奏效。 - JacksOnF1re
1
@KeivanEsbati 请检查答案! - Damia Fuentes
@DamiaFuentes 我会的!谢谢。 - Keivan Esbati
显示剩余3条评论
1个回答

2
请注意,所有这些都是在使用网络分页的Google示例上工作。虽然如此,思路已经很清晰了。
@Sarquella帮助我找到了这个解决方案。将这些类添加到您的项目中。基本上,我们正在扩展ViewHolder以成为LifeCycle Owner,因为默认情况下已经对ActivitiesFragments进行了扩展。 LifecycleViewHolder:
abstract class LifecycleViewHolder(itemView: View) :
        RecyclerView.ViewHolder(itemView),
        LifecycleOwner {

    private val lifecycleRegistry = LifecycleRegistry(this)

    fun onAttached() {
        lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
    }

    fun onDetached() {
        lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
    }

    override fun getLifecycle(): Lifecycle = lifecycleRegistry
}

LifecycleOwner 是一个只有一个方法的接口,表示该类具有 Lifecycle。您可以在此处找到更多信息。

LifecyclePagedListAdapter

abstract class LifecyclePagedListAdapter<T, VH : LifecycleViewHolder>(diffCallback: DiffUtil.ItemCallback<T>) :
        PagedListAdapter<T, VH>(diffCallback) {

    override fun onViewAttachedToWindow(holder: VH) {
        super.onViewAttachedToWindow(holder)
        holder.onAttached()
    }

    override fun onViewDetachedFromWindow(holder: VH) {
        super.onViewDetachedFromWindow(holder)
        holder.onDetached()
    }
}

如果需要,可以使用LifecycleAdapter

abstract class LifecycleAdapter<VH : LifecycleViewHolder> :
        RecyclerView.Adapter<VH>() {

    override fun onViewAttachedToWindow(holder: VH) {
        super.onViewAttachedToWindow(holder)
        holder.onAttached()
    }

    override fun onViewDetachedFromWindow(holder: VH) {
        super.onViewDetachedFromWindow(holder)
        holder.onDetached()
    }
}

然后,将MyAdapter扩展为LifecyclePagedListAdapter<MyEntity, LifecycleViewHolder>(MY_COMPARATOR),将MyViewHolder扩展为LifecycleViewHolder(view)。您需要根据我们所做的更改完成类。现在,我们可以观察MyViewHolder类上的liveData对象。因此,我们可以将其添加到MyViewHolder类中(假设您正在使用依赖注入)。基本上,我们将执行与FragmentsActivities相同的操作:
private lateinit var myViewModel: MyViewModel

init {
    (itemView.context as? AppCompatActivity)?.let{
        myViewModel = ViewModelProviders.of(it).get(MyViewModel::class.java)
    }
}

然后,在bind()方法内部:
fun bind(myCell: MyEntity?) {
    myViewModel.myLiveData.observe(this, Observer {
        // Buala!! Check if it is the cell you want to change and update it.
        if (it != null && myCell != null && it.id == myCell.id) {
           updateCell(it)
        }
    })
}

2
嗨,Damia,我可以问一下是否有演示所有必要更改的示例代码吗?当我浏览bind()方法和updateCell时,感到很迷茫。 - Tony Thompson
@Damia Fuentes,您能否请提供更新特定页面的工作示例。 - Badhrinath Canessane
@TonyThompson 你可以在这里找到一个实现所有这些更改以及示例应用程序的库:https://github.com/Sarquella/LifecycleCells - Sarquella
@BadhrinathCanessane 你可以在这里找到一个实现所有这些更改以及示例应用程序的库:https://github.com/Sarquella/LifecycleCells - Sarquella
由于某种原因,观察者从未被调用。我不明白为什么。 - isaacHerb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接