Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/179.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 更新房间整体性并遵守列表_Android_Android Room_Android Architecture Components_Android Livedata - Fatal编程技术网

Android 更新房间整体性并遵守列表

Android 更新房间整体性并遵守列表,android,android-room,android-architecture-components,android-livedata,Android,Android Room,Android Architecture Components,Android Livedata,想象一下,在主要活动中向您展示的帖子列表(如Facebook)。底层的“单一真相来源”是数据库,安卓的房间用来获取和观察这张帖子列表 这就是我观察数据的方式(由于许可证问题和简洁,细节被省略): 现在,每个帖子都有一个like按钮,以及单个帖子收到的like总数 现在,用户单击like按钮,您将发送一个操作。此操作可以执行以下操作: 1.1发出一个更新查询,增加帖子获得的喜欢次数 1.2标记数据库中的此特定帖子已被用户喜欢。 实际上,向服务器发送一个POST请求,并更新那里的工件。(除其他外,此

想象一下,在主要活动中向您展示的帖子列表(如Facebook)。底层的“单一真相来源”是数据库,安卓的房间用来获取和观察这张帖子列表

这就是我观察数据的方式(由于许可证问题和简洁,细节被省略):

现在,每个帖子都有一个like按钮,以及单个帖子收到的like总数

现在,用户单击like按钮,您将发送一个操作。此操作可以执行以下操作:

1.1发出一个更新查询,增加帖子获得的喜欢次数

1.2标记数据库中的此特定帖子已被用户喜欢。

  • 实际上,向服务器发送一个POST请求,并更新那里的工件。(除其他外,此用户喜欢的内容和帖子总数。)
  • 第二步是可行的,所以我们不要谈论它。但是,步骤1.1和1.2很棘手,因为当我发出更新查询时:

        @Query("UPDATE post SET liked= :liked, likes = likes + 1 WHERE id= :id")
        void updateLike(int id, int liked);
    
    (注意:这与不喜欢无关。它的效果类似于中等。一个用户可以给一篇文章N个喜欢。)

    无论如何,当我发出该查询时,它会更新数据库。因为,我实际上是使用
    LiveData
    观察这个数据库,所以我收到一个新的LiveData实体,然后将它连接到我的适配器上。我的适配器认为(数据集已更改),因此它更新了列表。执行此操作时,它还会滚动到列表中的第一篇文章。这就是问题所在

    我怎样才能防止呢

    一个可能的解决方案是检查传入列表和当前列表的post id是否相同,不要更新。但是,这意味着我不会从数据库中获得更新的
    No of likes
    和其他内容。这反过来意味着,当用户单击like按钮时,我必须手动更改视图中like的
    编号
    和like drawable的状态

    这是正确的方法吗?或者,我可以做些什么,让我的数据库成为“唯一的真相来源”,同时仍然拥有类似的按钮功能

    如果您使用的是
    RecyclerView.Adapter
    ,这意味着您有一个
    RecyclerView
    ViewPager2
    ,您可以使用它来解决您的问题

    首先,不应在每次db发出新数据时重新创建适配器

    当新数据可用时,您可以使用
    DiffUtil.calculateDiff(DiffUtil.Callback cb)
    获取
    DiffUtil.DiffResult
    对象,然后对结果调用
    dispatchUpdatesTo(适配器)

    这样,新旧数据之间的所有更改都将单独应用。例如,假设您的旧列表是
    A、B、C
    ,如果新列表是
    A、X、B、C
    ,则只有
    X
    将添加到RecyclerView(默认情况下,即使有动画)

    下面是一个示例实现:

    class ListDiffCalculator : DiffUtil.Callback() {
    
        private var oldList = emptyList<MyModel>()
        private var newList = emptyList<MyModel>()
    
        fun computeDiff(oldList: List<MyModel>, newList: List<MyModel>): DiffUtil.DiffResult {
            this.oldList = oldList
            this.newList = newList
            return DiffUtil.calculateDiff(this)
        }
    
        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
            oldList[oldItemPosition].id == newList[newItemPosition].id
    
        override fun getOldListSize() = oldList.size
    
        override fun getNewListSize() = newList.size
    
        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
            oldList[oldItemPosition].hashCode() == newList[newItemPosition].hashCode()
    }
    

    我实际上是在用LiveData观察这个数据库
    你是如何观察
    数据库的
    以及共享代码的。@AbdulKawee用代码片段更新了这个问题。谢谢你的回答,@lelloman。但是,我可以将DiffUtil与FragmentStatePagerAdapter+ViewPager一起使用吗?我不这么认为,我以为您使用的是回收器视图xD,但您可以。问题是RecyclerView.Adapter有方法通知特定的更改,而不仅仅是
    notifyDatasetChanged
    。哦,太好了。但这仍然是在阿尔法和我永远不会得到批准使用它在生产中现在:P谢谢你的回答。对未来的读者来说真的很有帮助。是的,你现在不应该在生产中使用它:D,但是PagerAdapter没有API来通知个别的更改,所以你必须通过黑客破解它。对。酷,我想我会实现我在问题中提到的黑客。如果我们有机会转到RecyclerView或ViewPage2,我们将返回此答案:谢谢
    class ListDiffCalculator : DiffUtil.Callback() {
    
        private var oldList = emptyList<MyModel>()
        private var newList = emptyList<MyModel>()
    
        fun computeDiff(oldList: List<MyModel>, newList: List<MyModel>): DiffUtil.DiffResult {
            this.oldList = oldList
            this.newList = newList
            return DiffUtil.calculateDiff(this)
        }
    
        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
            oldList[oldItemPosition].id == newList[newItemPosition].id
    
        override fun getOldListSize() = oldList.size
    
        override fun getNewListSize() = newList.size
    
        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
            oldList[oldItemPosition].hashCode() == newList[newItemPosition].hashCode()
    }
    
    class Adapter : RecyclerView.Adapter<ViewHolder>(), Observer<List<MyModel>> {
    
        private var data = emptyList<MyData>()  
    
        override fun onChanged(newData: List<MyModel>?) {
            newData?.let {
                val diff = listDiffCalculator.computeDiff(data, newData)
                this.data = newData
                diff.dispatchUpdatesTo(this)
            }
        }
    }
    
    aViewModel.getAllPosts().observe(getActivity(), adapter)