[英]Coroutine waiting for task in other function with same scope
I have a function like this that inserts a new row in a table with rowId:我有一个像这样的 function 在带有 rowId 的表中插入一个新行:
@Composable
fun AddNewCustomer() {
val db = CustomersDatabase.getDatabase(LocalContext.current)
val coroutineScope = rememberCoroutineScope()
val createMainEntity = {
coroutineScope.launch(Dispatchers.IO) {
val rowId = db.customersDao().getLast()!!.id + 1
db.customersDao().insertPrimaries(CustomersEntity(rowId, null, null, null))
}
}
createMainEntity()
otherFunc(db, coroutineScope)
}
and in another function, I insert a new row to another table:在另一个 function 中,我在另一个表中插入了一个新行:
@Composable
private fun otherFunc(
db: CustomersDatabase,
coroutineScope: CoroutineScope,
) {
val save = {
coroutineScope.launch(Dispatchers.IO) {
delay(100)
val rowId = db.customersDao().getLast()!!.id
db.customersDao().insertPhone(PhoneNumberEntity(phone = "", customerId = rowId , field = "" ))
}
}
save()
}
I want to save() in otherFunc
waits till createMainEntity finishes, with delay, I can be sure the createMainEntity
finishes first but it's a dirty way how can I do that better.我想 save() 在
otherFunc
等到 createMainEntity 完成,延迟,我可以确定createMainEntity
首先完成,但这是一种肮脏的方式,我怎样才能做得更好。
Based on what I understand about Compose, these functions absolutely should not be Composables.根据我对 Compose 的了解,这些函数绝对不应该是 Composables。 A Composable function must not affect external state because it must be idempotent.
可组合 function 不得影响外部 state,因为它必须是幂等的。 You could call one of these functions from a listener lambda in one of your Composables, but you must not call them directly.
您可以从您的其中一个 Composable 中的侦听器 lambda 调用这些函数之一,但不能直接调用它们。
Accordingly, the function name should not start with a capital letter by convention.因此,按照惯例,function 名称不应以大写字母开头。 I also added "Async" to the name to signify that it does something asynchronously (by launching a coroutine that runs separately).
我还在名称中添加了“Async”以表示它异步执行某些操作(通过启动单独运行的协程)。
To call the other function after the Room transaction is complete, call it inside the coroutine that is performing the transaction.要在 Room 事务完成后调用另一个 function,请在执行事务的协程内调用它。
Also, it is convoluted to create a lambda function solely to immediately call it and do nothing else with it, so I removed that.此外,创建一个 lambda function 只是为了立即调用它而不做任何其他事情,所以我删除了它。 Your fixed function looks like:
您固定的 function 看起来像:
fun addNewCustomerAsync(coroutineScope: CoroutineScope) {
val db = CustomersDatabase.getDatabase(LocalContext.current)
coroutineScope.launch(Dispatchers.IO) {
val rowId = db.customersDao().getLast()!!.id + 1
db.customersDao().insertPrimaries(CustomersEntity(rowId, null, null, null))
createMainEntity()
otherFunc(db, coroutineScope)
}
}
Your other function should simply be a suspend function.您的其他 function 应该只是暂停 function。 A dispatcher doesn't need to be specified because it doesn't call any blocking functions.
不需要指定调度程序,因为它不调用任何阻塞函数。
private suspend fun otherFunc(db: CustomersDatabase) {
delay(100) // Why are you doing this? Probably can remove this line.
val rowId = db.customersDao().getLast()!!.id
db.customersDao().insertPhone(PhoneNumberEntity(phone = "", customerId = rowId , field = "" ))
}
You can call addNewCustomerAsync()
from a listener/callback in one of your Composable functions, but you cannot call it directly.您可以在您的可组合函数之一中从侦听器/回调调用
addNewCustomerAsync()
,但不能直接调用它。 Really, these kinds of function that interact with a database should be in a ViewModel, so I would remove the coroutineScope
parameter from addNewCustomerAsync()
and have it use viewModelScope
.真的,这些与数据库交互的 function 应该在 ViewModel 中,所以我会从
addNewCustomerAsync()
中删除coroutineScope
参数并让它使用viewModelScope
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.