第一个问题在这里,我会尽力而为。
我有一个 Data 类,它在创建时使用 firestore 检索数据对象。我已经用协程为 setter 做了一些代码。我不确定我的解决方案,但它正在工作。但是,对于吸气剂,我正在努力等待初始化。
在初始化中,我有一个回调来检索数据。回调总是从主线程调用的问题,如果我在另一个线程的协程中使用它,则事件发生。我用以下方法检查:
Log.d("THREAD", "Execution thread1: "+Thread.currentThread().name)
对于 setter,我在 useTask 中使用协程来不阻塞主线程。还有一个互斥锁来阻塞这个协程,直到 init 中的初始化完成。不确定 waitInitialisationSuspend 但它正在工作。
但是对于getter,我只想阻塞主线程(即使它是糟糕的设计,它也是第一个解决方案)直到初始化完成,然后恢复getter以检索值。但是我不能阻止主线程而不阻止初始化中的回调,因为在同一个线程中。
我已经阅读了许多关于协程、作用域、runBlocking、线程等的文档,但我脑海中的一切都变得混乱了。
class Story(val id: String) : BaseObservable() {
private val storyRef = StoryHelper.getStoryRef(id)!!
private var isInitialized = false
private val initMutex = Mutex(true)
@get:Bindable
var dbStory: DbStory? = null
init {
storyRef.get().addOnCompleteListener { task ->
if (task.isSuccessful && task.result != null) {
dbStory = snapshot.toObject(DbStory::class.java)!!
if (!isInitialized) {
initMutex.unlock()
isInitialized = true
}
notifyPropertyChanged(BR.dbStory)
}
}
}
fun interface StoryListener {
fun onEvent()
}
private fun useTask(function: (task: Task) -> Unit): Task {
val task = Task()
GlobalScope.launch {
waitInitialisationSuspend()
function(task)
}
return task
}
private suspend fun waitInitialisationSuspend()
{
initMutex.withLock {
// no op wait for unlock mutex
}
}
fun typicalSetFunction(value: String) : Task {
return useTask { task ->
storyRef.update("fieldName", value).addOnSuccessListener {
task.doEvent()
}
}
}
fun typicalGetFunction(): String
{
var result = ""
// want something to wait the callback in the init.
return result
}
}
RunBlocking 似乎阻塞了主线程,所以如果回调仍然使用主线程,我无法使用它。如果我在主线程中使用 while 循环,也是同样的问题。
#1
runBlocking {
initMutex.withLock {
result = dbStory!!.value
}
}
#2
while (!isInitialized){
}
result = dbStory!!.value
#3 因为也许 init 中的回调也在主线程中。我尝试在带有 IO 调度程序的协程中启动此初始化,但没有成功。协程在不同的线程中很好,但回调仍然在主线程中调用。
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
scope.launch() {
reference.get().addOnCompleteListener { task ->
在 getter 中,我必须使用主线程。解决方案可能是将回调执行放在另一个线程中,但我不知道如何执行此操作。也许有更好的解决方案。
另一种解决方案是能够在不阻塞回调的情况下等待主线程中的回调,但我对此没有解决方案。
有任何想法吗 ?
我已经寻找了很多解决方案,结论是,不要这样做。
这个设计比我想象的要糟糕。Android 不希望您阻塞主线程,即使是很短的时间。阻塞主线程就是阻塞所有 UI 和同步机制,这真的是一个糟糕的解决方案。
我认为,即使使用另一个线程进行回调(您可以使用 Executor 执行)在这里也是一个坏主意。在回调中等待任务结束的好方法是检索任务并使用:
''' Tasks.await(initTask) '''
但是在主线程中是不允许的。Android 阻止你在这里做糟糕的设计。
我们应该处理管理firebase 数据库的异步方式,这是最好的方式。我仍然可以在数据上使用我的缓存。在这里,我正在等待显示一个对话框,其中包含我在 firebase 中检索到的文本。因此,我可以在检索文本数据时异步显示对话框。如果缓存可用,它将使用它。
还要记住,firebase 似乎有一些 API 来使用缓存。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句