标签: kotlin-sharedflow

Android kotlin 中 SharedFlow 的使用

嘿,我正在学习 kotlin 中的流程。我正在学习MutableStateFlowMutableSharedFlow。我尝试在现实世界的例子中学习MutableStateFlow。但我无法获得MutableSharedFlow示例,它更适合。我尝试了一些MutableStateFlow

例如,当我们从 api 获取数据时,我们可以使用 seal 类来进行相应的填充。

LoggedState.kt

sealed class LoggedState {
    data class OnSuccess(val data: List<XYZ>) : LoggedState()
    object OnEmpty : LoggedState()
    data class IsLoading(val isLoading: Boolean = true) : LoggedState()
    data class OnError(val message: String) : LoggedState()
} 
Run Code Online (Sandbox Code Playgroud)

设置ViewModel.kt

class SettingsViewModel : ViewModel() {

 var loggedMutableStateFlow = MutableStateFlow<LoggedState>(LoggedState.OnEmpty)

 fun fetchData(){
   val result = dataRepository.getLogged()
                result.handleResult(
                    onSuccess = { response ->
                        val data = response?.items
                        if (!data.isNullOrEmpty()) {
                            loggedMutableStateFlow.value …
Run Code Online (Sandbox Code Playgroud)

android kotlin kotlin-flow kotlin-stateflow kotlin-sharedflow

19
推荐指数
2
解决办法
1万
查看次数

MutableSharedFlow - 重放和 extraBufferCapacity 之间的区别

MutableSharedFlow 有 3 个参数:replay、extraBufferCapacity 和 onBufferOverflow。replay 和 extraBufferCapacity 有什么区别?

该文档提到以下内容:

replay - 重播给新订阅者的值的数量(不能为负数,默认为零)。

extraBufferCapacity - 除了重放之外缓冲的值的数量。当还有剩余缓冲区空间时,emit 不会暂停(可选,不能为负数,默认为零)。

我不明白两者之间的区别以及何时需要 extraBufferCapacity > 0。 extraBufferCapacity 只是发射器的额外重播能力吗?

android kotlin kotlin-coroutines kotlin-flow kotlin-sharedflow

17
推荐指数
1
解决办法
6676
查看次数

Channel 或 mutablesharedflow ,哪个是已弃用的 localbroadcastmanager 的更好替代品

过去,我LocalBroadcastManager and EventBus在聊天和出租车应用程序中使用这些应用程序,但现在这些应用程序要么已弃用,要么不建议使用它们。

我打算用新的数据结构替换它们,例如mutablesharedflow or channel,我想知道哪一个更适合我的情况?或者也许是另一种数据结构?

android channel kotlin kotlin-sharedflow

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

当新值与上一个值相同时 StateFlow 不会发出

我有一个登录表格。我用来StateFlow发送LoginResult(调用 API 之后)从ViewModelActivity。在活动中,如果登录失败,我将显示错误对话框。
第一次运行良好,但从第二次登录失败后,错误对话框将不再显示。我测试了.value两者.emitStateFlow

private val _loginResult = MutableStateFlow(LoginResult())
val loginResult: StateFlow<LoginResult> = _loginResult

fun login(email: String, password: String) {
    viewModelScope.launch {
        when (val result = loginRepository.login(email, password)) {
            is Result.Fail-> {
                _loginResult.value = LoginResult(error = "Login failed")
                // _loginResult.emit(LoginResult(error = "Login failed")) same issue
            }
            ...
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

android kotlin kotlin-stateflow kotlin-sharedflow

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

StateFlow最后一个值在ui中再次收集

最近,我一直在使用 StateFlow、SharedFlow 和 Channels API,但在尝试将代码从 LiveData 迁移到表示层中的 StateFlow 时,我遇到了一个常见用例。

我面临的问题是,当我发出数据并将其收集到 viewModel 中时,我可以将值设置为 mutableStateFlow,当它最终到达片段时,它会使用 Toast 显示一些信息性消息,让用户知道是否发生错误发生了或者一切都很顺利。接下来,有一个按钮可以导航到另一个片段,但是如果我返回到已经有失败意图结果的上一个屏幕,它会再次显示 Toast。这正是我想要弄清楚的。如果我已经收集了结果并向用户显示了消息,我不想继续这样做。如果我导航到另一个屏幕并返回(当应用程序从后台返回时也会发生这种情况,它会再次收集最后一个值)。LiveData 没有发生这个问题,我只是做了完全相同的事情,公开来自存储库的流并通过 ViewModel 中的 LiveData 收集。

代码:

class SignInViewModel @Inject constructor(
    private val doSignIn: SigninUseCase
) : ViewModel(){

    private val _userResult = MutableStateFlow<Result<String>?>(null)
    val userResult: StateFlow<Result<String>?> = _userResult.stateIn(viewModelScope, SharingStarted.Lazily, null) //Lazily since it's just one shot operation

    fun authenticate(email: String, password: String) {
        viewModelScope.launch {
            doSignIn(LoginParams(email, password)).collect { result ->
                Timber.e("I just received this $result in viewmodel")
                _userResult.value = result
            }
        }
    }
    
}
Run Code Online (Sandbox Code Playgroud)

然后在我的片段中: …

android kotlin kotlin-stateflow kotlin-sharedflow

9
推荐指数
2
解决办法
6668
查看次数

如何避免在片段恢复时重复执行Lifecycle

当导航回片段时,如何避免再次执行collect{}代码。

视图模型类

    private val _commitResult = MutableStateFlow<Map<String, Any>>(mapOf())
    val commitResult: StateFlow<Map<String, Any>> = _commitResult
Fragment code like this:

    viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED){
                viewModel.commitResult.collect { data ->
                    Logger.i("commitResult $data")
                    //navigate to another fragment
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

当我首先更改 viewModel 中的 _commitResult 值时,跳转到另一个片段效果很好。不幸的是,当我回到片段时。collect{ // navigate to another fragment}将再次执行。

我知道什么时候回到片段。onCreateView 再次执行,viewModel 会发出之前的数据存储,因此执行collect { // navigate to another fragment}。我怎样才能避免这种情况?

与 LiveData 相同,我使用 Event 来修复 LiveData 的问题。

open class Event<out T>(private val content: T) {

var hasBeenHandled = false
    private set // Allow …
Run Code Online (Sandbox Code Playgroud)

android kotlin-flow kotlin-sharedflow

9
推荐指数
1
解决办法
1400
查看次数

SharedFlow 不从发射中收集

在我的 ViewModel 中,我正在发出 API 请求,并且正在使用 FragmentStateFlowSharedFlow与 Fragment 进行通信。在发出 API 请求时,我可以轻松更新状态流的值,并将其成功收集到片段中。

但在发出请求之前,我发出了一些布尔值,SharedFlow并且它没有收集在片段中。有人可以帮助我为什么会发生这种情况吗?

class MainViewModel: ViewModel() {
  private val _stateFlow = MutableStateFlow(emptyList<Model>())
  val stateFlow = _stateFlow.asStateFlow()

  private val _loading = MutableSharedFlow<Boolean>()
  val loading = _loading.asSharedFlow()

  suspend fun request() {
    _loading.emit(true)
    withContext(Dispatchers.IO) {
      /* makes API request */
      /* updates _stateFlow.value */
      /* stateFlow value is successfully collected */
    }
    _loading.emit(false) // emitting boolean value
  }
}
Run Code Online (Sandbox Code Playgroud)
class MyFragment : Fragment(R.layout.fragment_my) {
   // ...

  override …
Run Code Online (Sandbox Code Playgroud)

android kotlin kotlin-coroutines kotlin-flow kotlin-sharedflow

7
推荐指数
2
解决办法
8545
查看次数

LiveData 转换为 StateFlow / SharedFlow

StateFlow / SharedFlow 中此实时数据转换的等效代码是什么?

val myLiveData: LiveData<MyLiveData> = Transformations
                    .switchMap(_query) {
                        if (it == null) {
                           AbsentLiveData.create()
                        } else {
                           repository.load()
                     }
Run Code Online (Sandbox Code Playgroud)

基本上,我想监听每个查询更改以对返回的内容做出反应。因此,任何类似于使用 StateFlow / SharedFlow 的东西都是受欢迎的。

kotlin android-livedata kotlin-flow kotlin-stateflow kotlin-sharedflow

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

清除 SharedFlow:将流转换为 mutableFlow

我有一个返回流的 API,我使用 shareIn() 将其转换为共享流。我有一个用例,我想重置共享流中的缓存值并强制流获取新数据。我们有一个resetReplayCache(),但它仅适用于 MutableSharedFlow。

class User(val id: String) {
   private val _flow = SharedFlow<Data> by lazy {
      Api.observeData(id).map {result-> transformData(result) } . shareIn(scope, timeout, 1)
   }

val flow = _flow


fun forceFetchNewData() {
   _flow.resetReplayCache()// how can I do this?
}
   
}
Run Code Online (Sandbox Code Playgroud)

我真的很感激一些关于将 shareFlow 转换为 mutableSharedFlow 或清空共享流缓存的指示

android kotlin kotlin-sharedflow

5
推荐指数
0
解决办法
991
查看次数

我什么时候应该在 Fragment 生命周期中收集 SharedFlow 事件

SharedFlow我认为收集数据是可以的onViewCreated。但是当我替换片段 n 次然后我触发一些事件时SharedFlow,它会向我发出 n 次事件而不是一个事件。

为了解决这个问题,我将代码放入onCreate片段中。我找不到任何相关文档。我是否遗漏了一些东西,或者我应该继续收集SharedFlow片段onCreate

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    lifecycleScope.launchWhenResumed {
        viewModel.uiEffect.collect {
            when (it) {
                is ViewEffectWrapper.PageEffect -> {
                    if (it.pageEvent is LoginViewEffect.OpenHomePage) {
                        startActivity(
                            Intent(
                                this@LoginFragment.context,
                                HomeActivity::class.java
                            )
                        )
                    }
                }

            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的SharedFlow定义ViewModel

private val _uiEffect = MutableSharedFlow<ViewEffectWrapper<LoginViewEffect>>(replay = 0)
val uiEffect: SharedFlow<ViewEffectWrapper<LoginViewEffect>> = _uiEffect
Run Code Online (Sandbox Code Playgroud)

android kotlin-coroutines kotlin-sharedflow

4
推荐指数
1
解决办法
3691
查看次数