#android #kotlin #kotlin-flow
#Android #котлин #котлин-поток
Вопрос:
Я очень новичок в потоках Котлина. Как следует из названия, у меня в основном есть 2 фрагмента, которые разделяют модель представления. Я хочу отправлять данные между ними, используя SharedFlow в качестве замены LiveData, не сохраняя его состояние.
Фрагмент А
class FragmentA: Fragment() { private lateinit var viewModelShared: SharedViewModel //Others// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModelShared = ViewModelProvider(requireActivity())[SharedViewModel::class.java] someView.setOnClickListener{ viewModelShared.sendData("Hello")} //Fragment Navigates From Fragment A to B using NavController navController.navigate(some_action_id) } }
Фрагмент В
class FragmentB: Fragment() { private lateinit var viewModelShared: SharedViewModel //Others// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModelShared = ViewModelProvider(requireActivity())[SharedViewModel::class.java] lifecycleScope.launchWhenCreated { viewModelMain.sharedFlow.collectLatest { //Data or the word 'Hello' sent from Fragment A not being Received Here } } }
Модель SharedViewModel
class SharedViewModel:ViewModel() { private val _sharedFlow= MutableSharedFlowlt;Stringgt;() val sharedFlow= _sharedFlow.asSharedFlow() fun sendData(data:String){ viewModelScope.launch { _sharedFlow.emit(data) } } }
Ответ №1:
Ваш фрагмент B собирается только тогда, когда он находится в начальном состоянии или выше. Это правильно, потому что вы не хотите работать с представлениями, когда они не видны и, возможно, в настоящее время не имеют представлений.
Однако, поскольку у вашего SharedFlow нет истории воспроизведения, это означает, что фрагменту B нечего собирать, когда он снова появится на экране. Предположительно, он находится за пределами экрана, когда FragmentA обновляет поток.
Таким образом, ваш общий поток без воспроизведения не имеет никакого отношения к тому, что в настоящее время у него нет коллекторов, и полученное значение выбрасывается. Чтобы это сработало, вам нужно повторить хотя бы 1 раз.
private val _sharedFlow= MutableSharedFlowlt;Stringgt;(replay = 1)
Вы упомянули «без сохранения его состояния», но это невозможно без состояния, если два фрагмента не отображаются на экране одновременно.
Кстати, есть более простой способ объявить вашу общую модель представления:
private val viewModelShared: SharedViewModel by activityViewModels()
Комментарии:
1. Большое вам спасибо, теперь это работает! Когда я сказал «сохранение его состояния», я имел в виду сохранение значения в n раз до тех пор, пока оно наблюдается. Извините за путаницу по этому поводу. Потоки Котлина действительно новы для меня, выглядят гибкими, но за счет кривой обучения по сравнению с LiveData, ха-ха.