#android #kotlin #kotlin-coroutines #kotlin-flow
Вопрос:
Я собираю данные из хранилища данных в потоках во вложенном запуске{}.
viewLifecycleOwner.lifecycleScope.launchWhenStarted { launch { DataStore.userName.collect { // it emits string value Log.e(TAG, it ) } } launch { DataStore.userPhone.collect { // it emits string value Log.e(TAG, it ) } } launch { DataStore.userAddress.collect { // it emits string value Log.e(TAG, it ) } } }
Есть ли лучший способ собирать потоки фрагментами ? Например, сбор всех данных в одном блоке запуска {}.
Комментарии:
1. Использование может использовать комбинацию :
fun lt;T1, T2, T3, Rgt; combine(flow: Flowlt;T1gt;, flow2: Flowlt;T2gt;, flow3: Flowlt;T3gt;, transform: suspend (T1, T2, T3) -gt; R): Flowlt;Rgt;
. Поэтому используйте здесьcombine(DataStore.userName, DataStore.userPhone, DataStore.userAddress, ::Triple).onEach{ (name, phone, address) -gt; .... }.launchIn(scope)
— подумайте о добавлении этого в качестве удобного метода вDataStore
.
Ответ №1:
Один из вариантов-объединить все потоки следующим образом:
combine(DataStore.userName, DataStore.userPhone, DataStore.userAddress) { userName, userPhone, userAddress -gt; // Operate on these values }
Другим вариантом может быть использование launchIn
, которое запускает сбор потока в предоставленной области сопрограммы.
viewLifecycleOwner.lifecycleScope.launchWhenStarted { DataStore.userName.onEach { userName -gt; // ... }.launchIn(this) DataStore.userPhone.onEach { userPhone -gt; // ... }.launchIn(this) DataStore.userAddress.onEach { userAddress -gt; // ... }.launchIn(this) }
launchIn
это просто сокращение для scope.launch { flow.collect() }
.
Комментарии:
1. Чтобы уточнить, функция combine() выдает новую комбинацию текущих значений из всех потоков источника всякий раз, когда один поток источника выдает новое значение. Это может быть желательным поведением, но может привести к нескольким избыточным операциям. Для уникальных комбинаций, таких как пользовательские данные, zip() может быть лучшим вариантом.
2. @nulldroid Можем ли мы использовать zip с несколькими потоками? Из того, что я помню, мы можем застегивать только два потока одновременно,
flow1.zip(flow2) { a,b -gt; }
3. Ой, как-то я об этом забыла. Вы правы, zip работает только с двумя потоками из коробки. В этом случае вам нужно будет сделать вложенный почтовый индекс. flow1.zip(поток 2) { a,b -gt; }.zip(поток 3) {ab, c -gt;gt; }
4. Zip будет выдавать только тогда, когда все потоки изменятся .. поэтому, например, если пользователь изменит свой адрес, последнее изменение адреса не будет замечено с помощью оператора zip. Также цепные молнии означают, что они неявно зависят от предыдущей операции с молнией, что может привести к другим проблемам. Combine-это правильный оператор, который объединяет последние из всех потоков, независимо от того, обновляются ли они независимо.
5. Все варианты приветствуются , я думаю, что я пойду с объединением трех потоков. Кажется, это решает мою проблему