![](/img/trans.png)
[英]Does a non suspend function inside a coroutine still run on another thread?
[英]How to run a suspend function inside another one without waiting for its result?
我有一個場景,我的代碼必須發送一個 api 調用並繼續其工作(其中包含另一個 api 調用),而無需等待第一次調用的結果。
現在我在我的視圖模型中這樣做
fun showItem(id:Int) {
launch{
repo.markItemRead(id)
}
launch {
try {
val item = repo.getItemById(id).getOrThrow
commands.postValue(ShowItemCommand(item))
} catch (t:Throwable) {
commands.postValue(ShowError(R.string.error_retrieve_item))
repo.logError(t)
}
}
}
這調用了具有這兩個功能的存儲庫
suspend fun markItemRead(id) {
try {
service.markItemAsRead(id)
} catch(ignored:Throwable) {
}
}
suspend fun getItemById(id) : Result<ItemData> {
return try {
val response : ItemEntity = service.getItemById(id)
val item = response.toData()
Result.Success(item)
} catch (t:Throwable) {
Result.Failure(t)
}
}
如果存儲庫完成所有這些工作,我會更喜歡它,因為每次都必須遵循另一個。
不幸的是,當我嘗試在我的存儲庫中做這樣的事情時:
suspend fun getItemById(id:Int) : Result<ItemData> {
try {
service.markItemAsRead(id)
} catch(ignored:Throwable) {
}
return try {
val response : ItemEntity = service.getItemById(id)
val item = response.toData()
Result.Success(item)
} catch (t:Throwable) {
Result.Failure(t)
}
}
它在繼續之前等待markItemAsRead
函數完成
除了定義存儲庫的范圍並將markItemAsRead
調用放在launch
中(我已經讀過在掛起函數中執行此操作是不正確的)之外,還有另一種方法可以在存儲庫中執行此操作嗎?
我有一個場景,我的代碼必須發送一個 api 調用並繼續其工作(其中包含另一個 api 調用),而無需等待第一次調用的結果。
現在我在我的視圖模型中這樣做
fun showItem(id:Int) {
launch{
repo.markItemRead(id)
}
launch {
try {
val item = repo.getItemById(id).getOrThrow
commands.postValue(ShowItemCommand(item))
} catch (t:Throwable) {
commands.postValue(ShowError(R.string.error_retrieve_item))
repo.logError(t)
}
}
}
這將調用具有這兩個功能的存儲庫
suspend fun markItemRead(id) {
try {
service.markItemAsRead(id)
} catch(ignored:Throwable) {
}
}
suspend fun getItemById(id) : Result<ItemData> {
return try {
val response : ItemEntity = service.getItemById(id)
val item = response.toData()
Result.Success(item)
} catch (t:Throwable) {
Result.Failure(t)
}
}
如果存儲庫完成所有這些工作,我會更喜歡它,因為每次都必須跟隨另一個。
不幸的是,當我嘗試在我的存儲庫中做這樣的事情時:
suspend fun getItemById(id:Int) : Result<ItemData> {
try {
service.markItemAsRead(id)
} catch(ignored:Throwable) {
}
return try {
val response : ItemEntity = service.getItemById(id)
val item = response.toData()
Result.Success(item)
} catch (t:Throwable) {
Result.Failure(t)
}
}
在markItemAsRead
之前等待markItemAsRead
函數完成
除了定義存儲庫的范圍並將markItemAsRead
調用放在launch
(我讀過在掛起函數中這樣做是不正確的)之外,還有另一種在存儲庫中執行此操作的方法嗎?
在存儲庫中還有另一種方法嗎?
不,沒有
(我讀過在掛起函數中這樣做是不正確的)
在掛起函數中使用launch
來完成即launch
即棄的任務是完全可以的
查看coroutineScope函數是否滿足您的要求:
創建一個 CoroutineScope 並使用此范圍調用指定的掛起塊。 提供的范圍從外部范圍繼承其 coroutineContext,但覆蓋上下文的 Job。
suspend fun getItemById(id:Int) : Result<ItemData> {
coroutineScope {
launch {
try {
service.markItemAsRead(id)
} catch(ignored:Throwable) { }
}
}
return try {
val response : ItemEntity = service.getItemById(id)
val item = response.toData()
Result.Success(item)
} catch (t:Throwable) {
Result.Failure(t)
}
}
您可以根據需要在存儲庫中使用coroutineScope
或supervisorScope
。 這兩個函數都是為並行分解工作而設計的。 一旦給定塊及其所有子協程完成,這些函數就會返回。
當 coroutineScope 中的任何子協coroutineScope
失敗時,此作用域將失敗,並且所有其余的子協程都將被取消。 與coroutineScope
不同, supervisorScope
中子協程的失敗不會導致此范圍失敗,也不會影響其其他子協程,因此可以實現處理其子協程失敗的自定義策略。
請選擇最適合您的需求。 使用示例:
suspend fun getItemByIdAndMarkRead(id: Int) : Result<ItemData> = supervisorScope {
launch {
try {
service.markItemAsRead(id)
} catch(ignored:Throwable) { }
}
return@supervisorScope withContext(Dispatchers.Default) {
try {
val response : ItemEntity = service.getItemById(id)
val item = response.toData()
Result.Success(item)
} catch (t: Throwable) {
Result.Failure(t)
}
}
}
service.markItemAsRead(id)
和service.getItemById(id)
將並行執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.