标签: kotlin-coroutines-flow

第一次发出 kotlin 协程后,MutableStateFlow 不发出值

这是我的 FirebaseOTPVerificationOperation 类,其中定义了我的 MutableStateFlow 属性,并更改了值,

    @ExperimentalCoroutinesApi
class FirebaseOTPVerificationOperation @Inject constructor(
    private val activity: Activity,
    val logger: Logger
) {
    private val _phoneAuthComplete = MutableStateFlow<PhoneAuthCredential?>(null)
    val phoneAuthComplete: StateFlow<PhoneAuthCredential?>
        get() = _phoneAuthComplete

    private val _phoneVerificationFailed = MutableStateFlow<String>("")
    val phoneVerificationFailed: StateFlow<String>
        get() = _phoneVerificationFailed

    private val _phoneCodeSent = MutableStateFlow<Boolean?>(null)
    val phoneCodeSent: StateFlow<Boolean?>
        get() = _phoneCodeSent

    private val _phoneVerificationSuccess = MutableStateFlow<Boolean?>(null)
    val phoneVerificationSuccess: StateFlow<Boolean?>
        get() = _phoneVerificationSuccess

    fun resendPhoneVerificationCode(phoneNumber: String) {
        _phoneVerificationFailed.value = "ERROR_RESEND"
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的视图模式,我在那里监听 stateflow 属性的变化,如下所示,

class OTPVerificationViewModal @AssistedInject constructor(
    private …
Run Code Online (Sandbox Code Playgroud)

kotlin kotlin-coroutines kotlin-coroutines-flow kotlin-coroutine-channel

14
推荐指数
4
解决办法
8666
查看次数

如何结束/关闭 MutableSharedFlow?

SharedFlow刚刚在协程 1.4.0-M1 中引入,它旨在替换所有BroadcastChannel实现(如设计问题描述中所述)。

我有一个用例,我使用 aBroadcastChannel来表示传入的 Web 套接字帧,以便多个侦听器可以“订阅”这些帧。当我移动到 a 时,我遇到的问题SharedFlow是当我收到关闭帧或上游错误时我无法“结束”流程(我想这样做是为了通知所有订阅者流程已经结束)。

当我想有效地“关闭” 时,如何使所有订阅终止SharedFlow?有没有办法区分正常关闭和异常关闭?(如频道)

如果MutableSharedFlow不允许将流的结尾传达给订阅者,如果BroadcastChannel被弃用/删除,有什么替代方法?

kotlin kotlin-coroutines kotlin-coroutines-flow

12
推荐指数
1
解决办法
2221
查看次数

初始化后如何修改 Kotlin Coroutine Flow 值?

预期的

初始化 Kotlin Coroutine Flow 并在 Flow 创建后修改其值。

所需的功能类似于 MutableLiveData 的功能setValue,它允许将数据添加到现有的 MutableLiveData 对象。在下面的示例中setValue,调用FeedViewModel.kt中的_feedMutableLiveData 值以更新该值。

这按预期工作,发出FeedFragment.kt 中的值

FeedViewState.kt

data class _FeedViewState(
    val _feed: MutableLiveData<List<Tweet>> = MutableLiveData()
)

data class FeedViewState(private val _feedViewState: _FeedViewState) {
    val feed: LiveData<List<Tweet>> = _feedViewState._feed
}
Run Code Online (Sandbox Code Playgroud)

FeedViewModel.kt

class FeedViewModel(...) : ViewModel() {
    private val _feedViewState = _FeedViewState()
    val feedViewState = FeedViewState(_feedViewState)
    init {
        viewModelScope.launch(Dispatchers.IO) {
            feedRepository.getFeed().collect { results ->
                when (results.status) {
                    LOADING -> ...
                    SUCCESS -> …
Run Code Online (Sandbox Code Playgroud)

android kotlin kotlin-coroutines kotlin-coroutines-flow

8
推荐指数
1
解决办法
3786
查看次数

如何将超过 2 个 api 调用的结果与 Coroutines Flow 相结合?

随着zip还是combine这只是可能的,如果我不想念什么只有2流结合起来,我没能看到流动的联合收割机列表或任何公共方法vararg

例如

apiHelper.getUsers()
            .zip(apiHelper.getMoreUsers()) { usersFromApi, moreUsersFromApi ->
                val allUsersFromApi = mutableListOf<ApiUser>()
                allUsersFromApi.addAll(usersFromApi)
                allUsersFromApi.addAll(moreUsersFromApi)
                return@zip allUsersFromApi
            }
Run Code Online (Sandbox Code Playgroud)

我需要来自 REST api 的前 5 个页面,并并行获取它们并组合结果,进行一些映射,并对组合数据进行过滤。我可以将它们与flow还是应该通过 coroutineScope 并使用 async 来进行并行请求?

我在这里查看了答案,但它返回编译错误,并且似乎没有将列表作为参数的流的公共组合函数。

android kotlin kotlin-coroutines kotlin-coroutines-flow

7
推荐指数
1
解决办法
3694
查看次数

将 MediatorLiveData 迁移到 SharedFlow

我有一个使用三个 LiveData 源的 MediatorLiveData。当它们中的任何一个发出一个新值并且我至少有一个值时,我使用这三个值来生成 UI 的输出。

其中两个来源是关于如何对列表进行排序和过滤的用户设置,第三个是从 Room 数据库 Flow 中提取的列表数据。

它看起来像这样:

val thingsLiveData: LiveData<List<Thing>> = object: MediatorLiveData<List<Thing>>() {
    var isSettingA: Boolean = true
    var settingB: MySortingEnum = MySortingEnum.Alphabetical
    var data: List<Thing>? = null
    init {
        addSource(myRepo.thingsFlow.asLiveData()) {
            data = it
            dataToValue()
        }
        addSource(settingALiveData) {
            isSettingA= it
            dataToValue()
        }
        addSource(settingBLiveData) {
            settingB= it
            dataToValue()
        }
    }
    private fun dataToValue() {
        data?.let { data ->
            viewModelScope.launch {
                val uiList = withContext(Dispatchers.Default) {
                    produceUiList(data, isSettingA, settingB)
                }
                value = listItems
            }
        } …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-room kotlin-coroutines kotlin-coroutines-flow

7
推荐指数
1
解决办法
846
查看次数

如何使用 Kotlin Flow 从异步回调中发出数据?

我开始学习 Kotlin Flow 和 Coroutines,但我不知道如何使下面的代码起作用。我究竟做错了什么?

interface MessagesListener {
    fun onNewMessageReceived(message: String)
}

fun messages(): Flow<String> = flow {

    val messagesListener = object : MessagesListener {
        override fun onNewMessageReceived(message: String) {

            // The line below generates the error 'Suspension functions can be called only within coroutine body'

            emit(message)
        }
    }

    val messagesPublisher = MessagesPublisher(messagesListener)
    messagesPublisher.connect()
}
Run Code Online (Sandbox Code Playgroud)

android kotlin kotlin-coroutines kotlin-coroutines-flow

6
推荐指数
2
解决办法
1846
查看次数

暂停 Kotlin 协程,直到流具有特定值

我目前正在使用 Kotlin 协程和流程。在我的场景中, aMutableStateFlow代表连接状态 ( CONNECTING, CONNECTED, CLOSING, CLOSED)。也可以登录、注销和再次登录。

为了进一步使用连接,我必须检查状态并等到它是CONNECTED. 如果已经是CONNECTED,我可以继续。如果没有,我必须等到状态达到CONNECTED. 该connect()调用不会返回通过可更新回调马上,结果被传播MutableStateFlow。我目前的想法是做以下事情:

connect()

if (connectionState.value != State.CONNECTED) { // connectionState = MutableStateFlow(State.CLOSED)

    suspendCoroutine<Boolean> { continuation ->
        scope.launch { // scope = MainScope()
            connectionState.collect {
                if (it == State.CONNECTED) {
                    continuation.resume(true)
                }
            }
        }
    }
}

// continue
Run Code Online (Sandbox Code Playgroud)

由于我对这个主题还很陌生,我不知道这是否是一种好的做法,而且我也无法在 Kotlin 文档中找到更合适的概念。有没有更好的方法来做到这一点?

android kotlin kotlin-coroutines kotlin-coroutines-flow

6
推荐指数
1
解决办法
720
查看次数

Kotlin 协程压缩三个流程

zip功能可以压缩两个Flows。有什么东西可以将三个(或更多)压缩Flows在一起吗?

如果没有,你能帮我实现它的扩展功能吗?就像是:

flow.zip(flow2, flow3) { a, b, c -> 

}
Run Code Online (Sandbox Code Playgroud)

kotlin kotlin-coroutines kotlin-coroutines-flow

5
推荐指数
1
解决办法
1486
查看次数

您应该将 coroutineScope 作为函数参数传递吗?

我正在试验协程,但不确定是否将 coroutineScope 传递给普通的 Kotlin 用例。这种方法会造成内存泄漏吗?

假设我们正在 VM 中初始化我们的 UseCase 并尝试传递viewModelScope

class UploadUseCase(private val imagesPreparingForUploadUseCase: ImagesPreparingForUploadUseCase){

fun execute(coroutineScope: CoroutineScope, bitmap: Bitmap) {
        coroutineScope.launch {
            val resizedBitmap = withContext(Dispatchers.IO) {
                imagesPreparingForUploadUseCase.getResizedBitmap(bitmap, MAX_SIZE)
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

是安全码吗?如果我在 VM 中声明这个确切的代码没有区别吗?如果不是,那意味着我可以将 coroutineScope 作为构造函数参数传递......现在我最初认为我应该通过以下方式创建我的 execute 方法:

fun CoroutineScope.execute(bitmap: Bitmap) {
        launch {
            val resizedBitmap = withContext(Dispatchers.IO) {
                imagesPreparingForUploadUseCase.getResizedBitmap(bitmap, MAX_SIZE)
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

据我所知,我们使用扩展函数以便方法使用父协程范围。这意味着,我不需要将 coroutineScope 作为参数传递,只需更改方法即可使用扩展函数。

但是,令我惊讶的是,VM 看不到此方法可用!为什么这个方法不能从VM调用?

这在 VM 中标记为红色:

 private fun uploadPhoto(bitmap: Bitmap, isImageUploaded: Boolean) {
        prepareDataForUploadingUseCase.execute(bitmap)
    }
Run Code Online (Sandbox Code Playgroud)

这在 …

kotlin android-mvvm kotlin-coroutines kotlin-coroutines-flow

5
推荐指数
2
解决办法
2214
查看次数

Kotlin Flow:当片段变得不可见时取消订阅 SharedFlow

我读过类似的主题,但找不到正确的答案:

在我的Repository班级我感冒了Flow,我想分享给 2 Presenters/ViewModels所以我的选择是使用shareIn运算符。

让我们看一下 Android 文档的示例:

val latestNews: Flow<List<ArticleHeadline>> = flow {
    ...
}.shareIn(
    externalScope,  // e.g. CoroutineScope(Dispatchers.IO)?
    replay = 1,
    started = SharingStarted.WhileSubscribed()
)
Run Code Online (Sandbox Code Playgroud)

什么文档建议externalScope参数:

用于共享流的 CoroutineScope。这个范围应该比任何消费者活得更久,以根据需要保持共享流的活动。

但是,寻找有关如何停止订阅 aFlow的答案,第二个链接中投票最多的答案说:

解决方案不是取消流程,而是取消流程的范围。

对我来说,这些答案在SharedFlow的情况下是矛盾的。不幸的是,即使在调用它之后,我的Presenter/ViewModel仍然会收到最新的数据onCleared

如何防止?这是我如何Flow在我的Presenter/ 中使用它的示例ViewModel …

android kotlin kotlin-coroutines kotlin-flow kotlin-coroutines-flow

5
推荐指数
1
解决办法
1549
查看次数