在片段和活动中,什么是运行阻塞协程的替代品? [英] What is the substitute for runBlocking Coroutines in fragments and activities?

查看:54
本文介绍了在片段和活动中,什么是运行阻塞协程的替代品?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

建议不要使用GlobalScope和runBlock。 我已经对这个主题进行了更改: End flow/coroutines task before go further null issue

然而,它不能像以前使用runBlock那样工作良好。简而言之,图标不变,数据不准时。 我的案例是根据布尔值更改图标。

对流程使用案例


class GetNotificationListItemDetailsUseCase @Inject constructor(private val notificationDao: NotificationDao): BaseFlowUseCase<Unit, List<NotificationItemsResponse.NotificationItemData>>() {
    override fun create(params: Unit): Flow<List<NotificationItemsResponse.NotificationItemData>> {
        return flow{
            emit(notificationDao.readAllData())
        }
    }
}

视图模型

    val actualNotificationList: Flow<List<NotificationItemsResponse.NotificationItemData>> = getNotificationListItemDetailsUseCase.build(Unit)
    

片段

    private fun getActualNotificationList() : Boolean {
        lifecycleScope.launch {
            vm.actualNotificationList
                .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
                .collect { response ->
                    notificationData.value = response
                    val notificationDataString = notificationData.value.toString()
                    val stringToCheck = "isRead=false"
                    isNotificationNotRead = (notificationDataString.contains(stringToCheck))
                }
        }
        return isNotificationNotRead
    }

在方法onViewCreated上,我让initToolbar检查它是否为真并执行操作,其中runBlokcing起作用。

fun initToolbar{
        if (onReceived) {
            Log.d("onReceivedGoes", "GOES IF")
        } else {
            Log.d("onReceivedGoes", "GOES ELSE")
            getActualNotificationList()
        }
        onReceived = false

        val item = menu.findItem(R.id.action_notification_list)
        when {
            isNotificationNotRead && !isOutcomed -> {
                item.setIcon(R.drawable.image_icon_change)
            }
}

变更前的协同工作,效果良好

        val job = GlobalScope.launch {
            vm.getNotificationListItemDetailsUseCase.build(Unit).collect {
                notificationData.value = it
                val notificationDataString = notificationData.value.toString()
                val stringToCheck = "isRead=false"
                isNotificationNotRead = (notificationDataString.contains(stringToCheck))
            }
        }
        runBlocking {
            job.join()
        }
    }

另一个问题是,我在MainActivity中也有同样的事情要做,但我在那里不使用流,只是暂停函数。

使用案例

class UpdateNotificationListItemUseCase @Inject constructor(private val notificationDao: NotificationDao): BaseUpdateBooleanUseCase<Int, Boolean, Boolean, Boolean, Unit>() {
    override suspend fun create(itemId: Int, isRead: Boolean, isArchived: Boolean, isAccepted: Boolean){
        notificationDao.updateBooleans(itemId, isRead, isArchived, isAccepted)
    }
}

维护活动

            val job = GlobalScope.launch { vm.getIdWithUpdate() }
            runBlocking {
                job.join()
            }

MainViewModel

suspend fun getIdWithUpdate() {
        var id = ""
        id = notificationAppSessionStorage.getString(
            notificationAppSessionStorage.getIncomingKeyValueStorage(),
            ""
        )
        if (id != "") {
           
            updateNotificationListItemUseCase.build(id.toInt(), true, false, false)
        }
    }
}

EDIT1:

收集碎片效果很好,谢谢

如何处理MainActivity和将此用例与Suspend Fun Without Flow一起使用。

我已阅读文档https://developer.android.com/kotlin/coroutines/coroutines-best-practices

        val IODispatcher: CoroutineDispatcher = Dispatchers.IO
        val externalScope: CoroutineScope = CoroutineScope(IODispatcher)
            suspend {
                externalScope.launch(IODispatcher) {
                    vm.getIdWithUpdate()
                }.join()
            }

第二个选项,但在这里我不会等到作业完成

            suspend {
                withContext(Dispatchers.IO) {
                    vm.getIdWithUpdate()
                }
            }

你觉得怎么样?

推荐答案

您可以尝试更新collect块中的图标:

private fun getActualNotificationList() = lifecycleScope.launch {
        vm.actualNotificationList
            .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
            .collect { response ->
                notificationData.value = response
                val notificationDataString = notificationData.value.toString()
                val stringToCheck = "isRead=false"
                val isNotificationNotRead = (notificationDataString.contains(stringToCheck))

                val item = menu.findItem(R.id.action_notification_list)
                when {
                    isNotificationNotRead && !isOutcomed -> {
                        item.setIcon(R.drawable.image_icon_change)
                    }
                }
            }
}

使用runBlocking会阻止主线程,这可能会导致ANR

这篇关于在片段和活动中,什么是运行阻塞协程的替代品?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆