【问题标题】:Emit function never collected in Kotlin Flow在 Kotlin Flow 中从未收集过 Emit 函数
【发布时间】:2020-08-13 12:13:22
【问题描述】:

我正在尝试使用一个函数来执行所有 API 调用和 Room 存储。但是在这个函数中,我有一个emit 不起作用。

fun getAPI() = flow {
    emit(State.Loading())
    // suspend function
    val response = safeApiCall{
        // retrofit request here
    }

    when (response) {
        is Success -> {
            // Emit here not working
            response.data?.let { emit(State.InsertOK(it)) }
            // Insert data in Room
            response.data?.let { insertQuery(it) }
        }
        is Error -> {
            emit(State.Error(response.error)
        }
    }
    
    emitAll(getQuery().map { State.Success(it) })
}

这些值收集在我的 ViewModel 中

private val _result = MutableLiveData<State<APIResult>>()
val result: LiveData<State<APIResult>>
        get() = _result 

fun getAPI( ) = viewModelScope.launch {
        repository.getAPI()
            .collect {
                _result .postValue(it)
            }
    }

我尝试在emit 之后和之前调用 DAO,但没有任何变化。 我是否对 Flow 做错了不打算像这样使用的事情?

【问题讨论】:

  • 好的。你能确认一件事,safeApiCall 不是异步调用或 myFlow() 函数内的另一个线程。
  • 它是一个挂起函数
  • 你能把收集方的代码粘贴过来吗?
  • 感谢您的更新!我怀疑 myFlow() 是 repository.getAPI()?
  • 是的!我会改正的

标签: android kotlin flow


【解决方案1】:

你应该调用一些terminal operator,例如collect()

myFlow().collect { value ->
    println("Received $value")
}

【讨论】:

  • 我知道,我是说在我的收藏中我没有得到发出的值
  • 可能response.data 为空?
  • 不,这就是我不明白的原因
  • 很有趣,如果你评论调用emitAll(getQuery()...),也许它会起作用
【解决方案2】:

流发射仅在启动的上下文中起作用,因此不确定您是否在某个地方启动到另一个上下文或其他东西。

但这里有一些解决方法。您可以返回 MutableStateFlow,并且可以像使用普通流一样收集,完全没有变化,但必须在函数定义处返回 MutableStateFlow。像下面的东西。用 ResponseModel 替换 api 您的响应。 MutableStateFlow 就像 livedata 一样,但具有流的好处,所以你不需要做太多的改变。

fun myFlow() = MutableStateFlow<State<ResponseModel>> {
    val mutableFlow = MutableStateFlow<State<ResponseModel>>(State.Loading())

    val response = safeApiCall{
        // retrofit request here
    }

    when (response) {
        is Success -> {
            // Emit here not working
            response.data?.let { mutableFlow.value = State.InsertOK(it) }
            // Insert data in Room
            response.data?.let { insertQuery(it) }
        }
        is Error -> {
            mutableFlow.value = State.Error(response.error)
        }
    }
    
   // emitAll(getQuery().map { State.Success(it) }) //here also assign value accordingly
   return mutableFlow
}

【讨论】:

  • 我添加了一个协程作用域,因为我已经暂停了函数。调用了发射,但我的挂起功能不再工作
猜你喜欢
  • 2021-10-28
  • 2022-06-10
  • 2022-12-15
  • 2023-01-02
  • 1970-01-01
  • 2016-01-21
  • 2020-09-30
  • 1970-01-01
  • 2017-09-22
相关资源
最近更新 更多