侦听Firebase数据库节点时如何处理Kotlin中的竞争条件

侦听Firebase数据库节点时如何处理Kotlin中的竞争条件

本文介绍了侦听Firebase数据库节点时如何处理Kotlin中的竞争条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,当我从事我的android项目时,我看到了我的应用程序的这种怪异行为.当我单击一个图标并转到另一个活动时,这基本上会将另一个孩子插入到第一个活动正在侦听的节点中.但是令我惊讶的是,当返回时,屏幕上的所有内容都翻了一番.当我刷新视图时,它又将恢复正常.我重复了很多次,认为这可能是一个小故障.但是每次都是一样的结果.当我查看数据库时,从未创建新的子代.

Today, when I was working on my android project, I saw this weird behavior of my app. When I click on an icon and move to a different activity, which would basically insert another child into the node to which first activity was listening to. But to my surprise, when return back, everything in the screen was doubled. When I refresh the view, it again would become normal. I repeated it many times, thinking it may be a glitch. But same result every time. When I look into database, new child was never created.

这是我给侦听器的代码. (doOnDataChange是扩展函数,我为onValueEventListener定义)

This is my code for listener. (doOnDataChange is an extension function, I defined for onValueEventListener)

val chats = mutableListOf<Chat>()
chatsListener = dbChatsReference.orderByChild(NODE_LAST_MESSAGE_TIME).doOnDataChange { it ->
    chats.clear()
    viewLifecycleOwner.lifecycleScope.launch(IO) {
        // some IO work
        for (ss in it.children) {
            Log.d(TAG, "onDataChange: ${ss.key!!} , ${Thread.currentThread()}")
            // populate chats with appropriate data
        }
    }
}

然后我记录了发生的情况.

Then I logged what's happening.

2020-12-08 23:52:39.721 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: cleared
2020-12-08 23:52:40.043 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: cleared
2020-12-08 23:52:40.132 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: j7ZmBA650WVmvd9z6BsN7UsvPlJ2VtDh2KtpeDhwXN386b580Lpr6dj2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:40.133 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2KQTXik3LjYMriCOdPoTKLNAtoVf2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:40.139 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2MWUYn8kW4MPlZvnn420XrN4p5kq2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:40.140 4114-4201/com.skb.skara D/ChatsFragment: onDataChange: j7ZmBA650WVmvd9z6BsN7UsvPlJ2VtDh2KtpeDhwXN386b580Lpr6dj2 , Thread[DefaultDispatcher-worker-3,5,main]
2020-12-08 23:52:40.141 4114-4201/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2KQTXik3LjYMriCOdPoTKLNAtoVf2 , Thread[DefaultDispatcher-worker-3,5,main]
2020-12-08 23:52:40.143 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2VtDh2KtpeDhwXN386b580Lpr6dj2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:40.145 4114-4201/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2MWUYn8kW4MPlZvnn420XrN4p5kq2 , Thread[DefaultDispatcher-worker-3,5,main]
2020-12-08 23:52:40.146 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2j7ZmBA650WVmvd9z6BsN7UsvPlJ2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:40.148 4114-4201/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2VtDh2KtpeDhwXN386b580Lpr6dj2 , Thread[DefaultDispatcher-worker-3,5,main]
2020-12-08 23:52:40.150 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: -MO2_oyUjEV55HAGlzXN , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:40.152 4114-4201/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2j7ZmBA650WVmvd9z6BsN7UsvPlJ2 , Thread[DefaultDispatcher-worker-3,5,main]
2020-12-08 23:52:45.395 4114-4114/com.skb.skara D/ChatsFragment: onCreateView:
2020-12-08 23:52:45.842 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: cleared
2020-12-08 23:52:46.263 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: j7ZmBA650WVmvd9z6BsN7UsvPlJ2VtDh2KtpeDhwXN386b580Lpr6dj2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:46.264 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2KQTXik3LjYMriCOdPoTKLNAtoVf2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:46.268 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2MWUYn8kW4MPlZvnn420XrN4p5kq2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:46.273 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2VtDh2KtpeDhwXN386b580Lpr6dj2 , Thread[DefaultDispatcher-worker-2,5,main]
2020-12-08 23:52:46.278 4114-4200/com.skb.skara D/ChatsFragment: onDataChange: lIq43hHgzKfsE0zbYIeiH4dhswT2j7ZmBA650WVmvd9z6BsN7UsvPlJ2 , Thread[DefaultDispatcher-worker-2,5,main]

然后,我想起了博客,当您对数据库进行一些更改时,将立即触发侦听器,而无需实际等待写入完成.此后,如果写入失败,则将使用旧值再次触发侦听器,以使之前的触发器无效.由于我在这里使用了协程,因此聊天列表由两个线程同时更新.即使对节点进行了两次更改且之间的延迟很短,也会发生这种情况.

Then I remembered, as mentioned in this blog, when you make some changes to database, immediately listeners are triggered, without actually waiting for the write to complete. Afterwards, if the write fails, the listeners are triggered again with the old values to nullify the previous trigger. Since I have used coroutines here, chats list is being updated simultaneously by two threads. This can happen even when two changes are made to the node with very short delay in between.

所以有人可以告诉我如何克服这种比赛条件.

So can someone tell me how to overcome this race condition.

推荐答案

避免使用可变列表和数据类,而只需在数据上使用map即可将其转换为所需类型的只读列表您的列表视图.

Avoid using mutable lists and data classes, but rather just use map on your data to transform it to a read-only List of the type you need for your list view.

使您的RecyclerView.Adapter存储一个var属性,以便立即对其进行更改.更改数据列表,然后调用notifyDataSetChanged().然后,它一次只能查看一个列表.

Make your RecyclerView.Adapter store a var property so it is changed all at once. Change the data list and call notifyDataSetChanged(). Then it is only ever looking at one list at a time.

这篇关于侦听Firebase数据库节点时如何处理Kotlin中的竞争条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 17:13