From 42e2dd1945223c2fc2c747260cb6ba08cb68e1bf Mon Sep 17 00:00:00 2001 From: Dmitry Ryaboshapko Date: Sun, 25 Jan 2026 19:09:00 +0300 Subject: [PATCH 1/3] =?UTF-8?q?=D0=92=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=BF=D0=BE=20FLow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../otus/homework/flowcats/CatsViewModel.kt | 38 +++++++++++++--- .../otus/homework/flowcats/MainActivity.kt | 25 ++++++++++- .../otus/homework/flow/SampleInteractor.kt | 45 +++++++++++++++++-- 3 files changed, 95 insertions(+), 13 deletions(-) diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index 0d8ba8a7..090264a9 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -1,7 +1,13 @@ package otus.homework.flowcats -import androidx.lifecycle.* +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -10,22 +16,40 @@ class CatsViewModel( private val catsRepository: CatsRepository ) : ViewModel() { - private val _catsLiveData = MutableLiveData() - val catsLiveData: LiveData = _catsLiveData + private val _catsStateFlow = MutableStateFlow(Result.Success(Unit)) + val catsStateFlow = _catsStateFlow.asStateFlow() init { viewModelScope.launch { withContext(Dispatchers.IO) { - catsRepository.listenForCatFacts().collect { - _catsLiveData.value = it + catsRepository.listenForCatFacts() + .catch { error -> + _catsStateFlow.emit( + Result.Error( + error.message.orEmpty(), + ), + ) + } + .collect { fact -> + _catsStateFlow.emit( + Result.Success(fact), + ) } } } } } +sealed interface Result { + data class Success(val result: T) : Result + @JvmInline + value class Error(val message: String) : Result +} + +@Suppress("UNCHECKED_CAST") class CatsViewModelFactory(private val catsRepository: CatsRepository) : ViewModelProvider.NewInstanceFactory() { - override fun create(modelClass: Class): T = - CatsViewModel(catsRepository) as T + override fun create(modelClass: Class): T { + return CatsViewModel(catsRepository) as T + } } \ No newline at end of file diff --git a/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt b/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt index edea434b..d95fe465 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt @@ -2,20 +2,41 @@ package otus.homework.flowcats import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.util.Log import androidx.activity.viewModels +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { private val diContainer = DiContainer() private val catsViewModel by viewModels { CatsViewModelFactory(diContainer.repository) } + @OptIn(InternalCoroutinesApi::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView setContentView(view) - catsViewModel.catsLiveData.observe(this){ - view.populate(it) + lifecycleScope.launchWhenStarted { + launch { + catsViewModel.catsStateFlow.collect { result -> + when (result) { + is Result.Success<*> -> { + val fact = result.result as? Fact + if (fact != null) { + view.populate(result.result) + } + } + + is Result.Error -> { + Log.d("Error", result.message) + } + } + } + } } } } \ No newline at end of file diff --git a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt index 1993c064..64ac226a 100644 --- a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt +++ b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt @@ -2,6 +2,7 @@ package otus.homework.flow import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.* +import java.util.function.BiFunction @ExperimentalCoroutinesApi class SampleInteractor( @@ -18,7 +19,12 @@ class SampleInteractor( * 6) возвращает результат */ fun task1(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .map { it * 5 } + .filter { it >= 20 } + .filterNot { it % 2 == 0 } + .map { "$it won" } + .take(3) } /** @@ -29,7 +35,24 @@ class SampleInteractor( * Если число не делится на 3,5,15 - эмитим само число */ fun task2(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .transform { + when { + it % 15 == 0 -> { + emit(it.toString()) + emit("FizzBuzz") + } + it % 5 == 0 -> { + emit(it.toString()) + emit("Buzz") + } + it % 3 == 0-> { + emit(it.toString()) + emit("Fizz") + } + else -> emit(it.toString()) + } + } } /** @@ -38,7 +61,12 @@ class SampleInteractor( * Если айтемы в одно из флоу кончились то результирующий флоу также должен закончится */ fun task3(): Flow> { - return flowOf() + return sampleRepository.produceColors().zip( + sampleRepository.produceForms(), + ) { color, form -> + color to form + } + } /** @@ -48,6 +76,15 @@ class SampleInteractor( * При любом исходе, будь то выброс исключения или успешная отработка функции вызовите метод dotsRepository.completed() */ fun task4(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .catch { error -> + if (error is IllegalArgumentException) { + emit(-1) + } else { + throw error + } + }.onCompletion { + sampleRepository.completed() + } } } \ No newline at end of file From 4bf7575d70cd0f5b2ffa46b032f5380da697b2ea Mon Sep 17 00:00:00 2001 From: Dmitry Ryaboshapko Date: Fri, 30 Jan 2026 16:05:03 +0300 Subject: [PATCH 2/3] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/otus/homework/flowcats/CatsRepository.kt | 8 +++++++- .../java/otus/homework/flowcats/CatsViewModel.kt | 13 ++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt index 10fcb77d..51a6e088 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt @@ -1,6 +1,8 @@ package otus.homework.flowcats import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flow class CatsRepository( @@ -11,8 +13,12 @@ class CatsRepository( fun listenForCatFacts() = flow { while (true) { val latestNews = catsService.getCatFact() - emit(latestNews) + emit(Result.Success(latestNews)) delay(refreshIntervalMs) } + }.catch { error -> + Result.Error( + error.message.orEmpty(), + ) } } \ No newline at end of file diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index 090264a9..d7d55d11 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -23,18 +23,9 @@ class CatsViewModel( viewModelScope.launch { withContext(Dispatchers.IO) { catsRepository.listenForCatFacts() - .catch { error -> - _catsStateFlow.emit( - Result.Error( - error.message.orEmpty(), - ), - ) - } .collect { fact -> - _catsStateFlow.emit( - Result.Success(fact), - ) - } + _catsStateFlow.emit(fact) + } } } } From dd84bc5cc67169d05e3107a8586cb7b1253f4ee4 Mon Sep 17 00:00:00 2001 From: Dmitry Ryaboshapko Date: Sat, 31 Jan 2026 18:50:09 +0300 Subject: [PATCH 3/3] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index d7d55d11..14df9fd3 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -1,13 +1,11 @@ package otus.homework.flowcats -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import kotlinx.coroutines.withContext