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

Ada*_*itz 8 android kotlin kotlin-coroutines kotlin-coroutines-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 -> withContext(Dispatchers.Main) {
                        _feedViewState._feed.value = results.data
                    }
                    ERROR -> ...
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

FeedFragment.kt

class FeedFragment : Fragment() {
    override fun onCreateView(...): View? {
        viewModel.feedViewState.feed.observe(viewLifecycleOwner){ feed ->
                //Do something with the tweets here.
        }        
        return inflater.inflate(R.layout.fragment_feed, container, false)
    }
}
Run Code Online (Sandbox Code Playgroud)

观察到的

为了使用 Kotlin 协程实现相同的模式,FeedViewState.kt 中的LiveData被替换为 Flow。在FeedViewModel.kt 中,所需的结果是向_feedFlow 值添加数据。尝试的解决方案是将map、 和emit内部transform和 应用onCompletion_feedFlow 值。

但是,此解决方案不会从FeedFragment.kt 中的 Flow 值发出所需的值。

FeedViewState.kt

data class _FeedViewState(
    val _feed: Flow<List<Tweet>> = flow { }
)

data class FeedViewState(private val _feedViewState: _FeedViewState) {
    @ExperimentalCoroutinesApi
    val feed: Flow<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 -> withContext(Dispatchers.Main) {
                        _feedViewState._feed.map { results.data!! }
                    }
                    ERROR -> ...
                }
            }
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

FeedFragment.kt

class FeedFragment : Fragment() {
    override fun onCreateView(...): View? {
        lifecycleScope.launch {
            viewModel.feedViewState.feed.collect { tweets ->
                //Do something with the tweets here.
            }
        }
        return inflater.inflate(R.layout.fragment_feed, container, false)
    }
}
Run Code Online (Sandbox Code Playgroud)