如何在更新函数上操作的数据时重新启动函数



在片段的onCreateView()方法中,我将3个valueEventListener附加到firebase数据库中不同的互斥位置。每当引用处的数据被更新时,它们都会被异步触发。我的示例代码如下:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
listner1 = ref1.addCustomValueEventListener {
list1.clear()
// do some operation and populate list1
rewriteMainData()
}
listner2 = ref2.addCustomValueEventListener {
list2.clear()
// do some operation and populate list2
rewriteMainData()
}
listner3 = ref3.addCustomValueEventListener {
list3.clear()
// do some operation and populate list3
rewriteMainData()
}
}
private fun rewriteMainData() {
mainList.clear()
mainDbReference.addCustomListenerForSingleValueEvent {
// compare the values present here with values in list1, list2, list3
// populate mainList with appropriate values
// notifyAdapterDataSetChanged
}
return
}
// EXTENSION FUNCTION
internal inline fun DatabaseReference.addCustomValueEventListener(crossinline onDataChange: (DataSnapshot) -> Unit) =
addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
onDataChange(snapshot)
}
override fun onCancelled(error: DatabaseError) {
Log.e(TAG, "onCancelled: ", error.toException())
}
})

然而,在本例中,如果一个监听器在另一个监听器之后很快被触发,那么rewriteMainData()将被调用两次。届时,mainList将由两个回调同时写入。解决此问题的一种方法是使用ReentrantLock的实例来避免同时写入。但这使得最近的调用要等到上一次调用完成,这是多余的,因为所有数据都将被清除和重写
因此,是否有任何方法可以知道rewriteMainData()何时被调用,如果它已经在运行,那么只需中止并重新启动具有更新列表的函数?

每次在做任何密集的工作之前,都可以检查当前协同程序的取消情况。

// instance variable on the class
var job1: Job? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
ref1.addCustomValueEventListener {
job1?.cancel()
job2?.cancel()
job3?.cancel()
job1 = lifecycleScope.launch(Dispatchers.Default) {
list1.clear()

// do some operation and populate list1
rewriteMainData()
}
}
// ...
}

private suspend fun rewriteMainData() {
mainList.clear()
// before every intensive work, to check for cancellation.
yield()
// some work involving cpu consumption or takes significant time.
}

请注意,如果工作只是同步更新列表,这只需要几个CPU周期和毫秒的时间,那么这种影响非常小,甚至更糟。只有当您确信rewriteMainData在当前代码中所做的工作会对性能产生影响时,才使用此选项。

mainList将由两个回调同时写入。

这在您这里的代码中是不可能的。默认情况下,数据库回调是在Android主线程上调用的,这意味着它们不能同时调用。它们将按顺序调用。因此,您不必担心线程或锁定。

相关内容

  • 没有找到相关文章

最新更新