gpt4 book ai didi

android - 为什么我可以在同一个线程中操作 UI 和访问数据库?

转载 作者:行者123 更新时间:2023-11-29 18:28:00 26 4
gpt4 key购买 nike

刚刚发现我对线程的理解存在差距。我有以下函数将一些结果保存到数据库并离开 Activity :

private fun leave() {
GlobalScope.launch {
prepareForSaving()
println("thread:${Thread.currentThread()}")
gameData.save.id = JigsawDatabase(this@GameActivity).savesDao().upsert(gameData.save).toInt()
val resIntent = Intent()
val res=Gson().toJson(result)
resIntent.putExtra("gameResult",res)
setResult(0, resIntent)
finish()
}
}

从一侧 println 打印 thread:Thread[DefaultDispatcher-worker-1,5,main] 说它的工作线程。但我仍然可以访问 UI 作为 finish() 工作正常。完全糊涂了。
更新:将 GlobalScore 更改为我的 viewModel 的 coroutineScope 时出现异常:

private fun leave() {
model.viewModelScope.launch {
gameData.save.id =
JigsawDatabase(this@GameActivity).savesDao().upsert(gameData.save).toInt()// throws Cannot access database on the main thread
...
finish()
}
}

有趣的是,即使我将上下文指定为 model.viewModelScope.launch(Dispatchers.IO),它仍然可以访问 UI。这对我来说毫无意义

最佳答案

长话短说Android 对访问不应该在 UI 线程上完成的事情进行了严格检查,但对不应该在工作线程上完成的事情进行的硬检查并不多。

解释

这里有几件事。关于协程,如果您真正使用 GlobalScope 或任何作用域,而没有指定它将在哪个调度程序上运行,它将在 Dispatcher.Default 上运行,这是计算线程。

GlobalScope.launch {
// This is why you print thread:Thread[DefaultDispatcher-worker-1,5,main] here
println("thread:${Thread.currentThread()}")
}

现在工作线程确实可以访问/更新你的数据库

gameData.save.id = JigsawDatabase(this@GameActivity).savesDao().upsert(gameData.save).toInt()

正如您提到的,您还更新了调用 finish() 的 UI,并且没有发生崩溃。

这是因为并非所有方法(大多数 View 方法实际上不检查这一点)都有检查以确保它们没有被主线程访问。只有几件事可以检查这一点。

以实时数据的 setValue 方法为例,

@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}

private static void assertMainThread(String methodName) {
if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
}

这实际上是明确检查以确保您在 MainThread 而不是工作线程上调用此更新,并且是大多数 UI 元素没有的检查。它们可能只是以某种难以在运行时调试的方式失败。

调用数据库时出现异常

当您切换到 viewModel 范围时,您可能已将其设置为 Dispatchers.Main

那时,如果您想调用明确检查以确保它是在工作线程(如 Room 数据库)上调用的东西,您将遇到此崩溃。

Cannot access database on the main thread since it may potentially lock the UI for a long periods of time.

关于android - 为什么我可以在同一个线程中操作 UI 和访问数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57834495/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com