Kotlin SharedFlow ViewModel излучает до подписки
Я пытаюсь использовать SharedFlow в качестве поставщика данных для фрагмента в архитектуре MVVM.
В классе Фрагмент:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.data.collect { value ->
handleData(data)
}
}
}
viewModel.init()
}
В классе ViewModel:
private val _data: MutableSharedFlow<DataState> = MutableSharedFlow()
val data: SharedFlow<DataState> = _data
fun init() {
...
//(listen for other data providers that generate data for SharedFlow)
...
viewModelCoroutineScope.launch {
val dataCollection = interactor.getDataCollection()
dataCollection.forEach { data ->
if (data != null) {
_data.emit(DataState(data = data))
}
}
}
}
Проблема в том, что в 50% случаев запускается до того, как подписчик под прицелом подключится к Flow, что приводит к потере части данных. Почему используется SharedFlow? Это связано с тем, что у ViewModel есть подписки на другие источники данных, которые могут отправлять множество экземпляров данных нерегулярным образом, все, что необходимо для сбора, поэтому StateFlow/LiveData с их «сохранением только последнего значения» не подходит для этого.
Когда я пытался закрепить
viewmodel.init()
для сопрограммы подписчика следующим образом:
val job = viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.data.collect { value ->
handleData(data)
}
}
}
viewLifecycleOwner.lifecycleScope.launch {
job.join()
viewModel.init()
}
ViewModel выдает данные, но Fragment никогда их не собирает.
Как правильно гарантировать, что подписчики включены до вызова ViewModel, чтобы начать отправку данных через SharedFlow?