在出现进一步的空问题之前结束流/协同程序任务 [英] End flow/coroutines task before go further null issue

查看:106
本文介绍了在出现进一步的空问题之前结束流/协同程序任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

片段

   private fun makeApiRequest() {
        vm.getRandomPicture()
        var pictureElement = vm.setRandomPicture()

        GlobalScope.launch(Dispatchers.Main) {
            // what about internet
            if (pictureElement != null && pictureElement!!.fileSizeBytes!! < 400000) {

                Glide.with(requireContext()).load(pictureElement!!.url)
                    .into(layout.ivRandomPicture)
                layout.ivRandomPicture.visibility = View.VISIBLE
            } else {
                getRandomPicture()
            }
        }
    }

视图模型

    fun getRandomPicture() {
        viewModelScope.launch {
            getRandomPictureItemUseCase.build(Unit).collect {
                pictureElement.value = it
                Log.d("inspirationquotes", "VIEWMODEL $pictureElement")
                Log.d("inspirationquotes", "VIEWMODEL VALUE ${pictureElement.value}")
            }
        }
    }

    fun setRandomPicture(): InspirationQuotesDetailsResponse? {
            return pictureElement.value
    }

流程使用案例

class GetRandomPictureItemUseCase @Inject constructor(private val api: InspirationQuotesApi): BaseFlowUseCase<Unit, InspirationQuotesDetailsResponse>() {
    override fun create(params: Unit): Flow<InspirationQuotesDetailsResponse> {
        return flow{
            emit(api.getRandomPicture())
        }
    }
}

我从视图模型执行的流任务没有按时执行。我不知道如何从API顺利下载数据并进一步提供。 我读到我可以使用runBlock,但在生产中不推荐这样做。 您在专业应用程序中使用什么来实现漂亮的应用程序?

现在的效果是图像无法加载,或者由于片段中GlobalScope之前的Log.d错误为空(它目前不在代码中)。

还有一件事是定义空对象我不喜欢,你觉得呢?

    var pictureElement = MutableStateFlow<InspirationQuotesDetailsResponse?>(null)

编辑:

查看模型

 val randomPicture: Flow<InspirationQuotesDetailsResponse> = getRandomPictureItemUseCase.build(Unit)

片段

private fun makeApiRequest() = lifecycleScope.launch {
            vm.randomPicture
                .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
                .collect { response ->
                    if (response.fileSizeBytes < 600000) {
                        Log.d("fragment", "itGetsValue")
                        Glide.with(requireContext()).load(response.url)
                            .into(layout.ivRandomPicture)
                        layout.ivRandomPicture.visibility = View.VISIBLE
                    } else {
                        onFloatingActionClick()
                    }
                }
    }

编辑2生产问题,另一个主题: Link-gt;What is the substitute for runBlocking Coroutines in fragments and activities?

推荐答案

首先,不要使用GlobalScope启动协程,这是非常不鼓励的,而且容易出现错误。使用Fragment中提供的lifecycleScope

lifecycleScope.launch {...}

使用MutableSharedFlow代替MutableStateFlowMutableSharedFlow不需要初始值,可以去掉可以为空的泛型:

val pictureElement = MutableSharedFlow<InspirationQuotesDetailsResponse>()

但我想我们可以摆脱它。

GetRandomPictureItemUseCase中的方法create()返回仅发出一个值的Flow,它是否真的需要是Flow,或者它可以只是一个简单的suspend函数?

假设我们坚持GetRandomPictureItemUseCase类中的FlowViewModel可能如下所示:

val randomPicture: Flow<InspirationQuotesDetailsResponse> = getRandomPictureItemUseCase.build(Unit)

Fragment中:

private fun makeApiRequest() = lifecycleScope.launch {
    vm.randomPicture
      .flowWithLifecycle(lifecycle, State.STARTED)
      .collect { response ->
          // .. use response
      }
}

要使用的依赖项lifecycleScope

implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'

这篇关于在出现进一步的空问题之前结束流/协同程序任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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