From 464d905403e4bf8e21a13042166a15c7f4125756 Mon Sep 17 00:00:00 2001 From: Ivan Toropygin Date: Sun, 25 Jan 2026 15:02:08 +0300 Subject: [PATCH 1/3] Task 1 --- .../otus/homework/flowcats/CatsRepository.kt | 11 +++--- .../java/otus/homework/flowcats/CatsView.kt | 20 ++++++++++- .../otus/homework/flowcats/CatsViewModel.kt | 36 +++++++++++++------ .../otus/homework/flowcats/MainActivity.kt | 26 +++++++++++--- .../src/main/res/layout/activity_main.xml | 9 +++-- 5 files changed, 79 insertions(+), 23 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..38267134 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt @@ -7,11 +7,14 @@ class CatsRepository( private val catsService: CatsService, private val refreshIntervalMs: Long = 5000 ) { - - fun listenForCatFacts() = flow { + fun listenForCatFacts() = flow> { while (true) { - val latestNews = catsService.getCatFact() - emit(latestNews) + try { + val latestNews = catsService.getCatFact() + emit(Result.Success(latestNews)) + } catch (e: Exception) { + emit(Result.Error(e)) + } delay(refreshIntervalMs) } } diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt index 6a195f3a..770258f7 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt @@ -11,8 +11,26 @@ class CatsView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView { + private lateinit var textView: TextView + + override fun onFinishInflate() { + super.onFinishInflate() + textView = findViewById(R.id.fact_textView) + } + override fun populate(fact: Fact) { - findViewById(R.id.fact_textView).text = fact.text + textView.text = fact.text + textView.setTextColor(context.getColor(android.R.color.black)) + } + + fun showError(errorMessage: String) { + textView.text = "Error: $errorMessage" + textView.setTextColor(context.getColor(android.R.color.holo_red_dark)) + } + + fun showLoading() { + textView.text = "Loading..." + textView.setTextColor(context.getColor(android.R.color.darker_gray)) } } diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index 0d8ba8a7..247bfda8 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -1,31 +1,47 @@ package otus.homework.flowcats -import androidx.lifecycle.* +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.StateFlow import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext class CatsViewModel( private val catsRepository: CatsRepository ) : ViewModel() { - private val _catsLiveData = MutableLiveData() - val catsLiveData: LiveData = _catsLiveData + private val _catsState = MutableStateFlow>(Result.Loading) + val catsState: StateFlow> = _catsState init { + loadCatFacts() + } + + private fun loadCatFacts() { viewModelScope.launch { - withContext(Dispatchers.IO) { - catsRepository.listenForCatFacts().collect { - _catsLiveData.value = it + catsRepository.listenForCatFacts() + .flowOn(Dispatchers.IO) + .collect { result -> + _catsState.value = result } - } } } } 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 + } +} + +sealed class Result { + data class Success(val data: T) : Result() + data class Error(val exception: Throwable) : Result() + + object Loading : Result() } \ 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..9264cbfe 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt @@ -1,21 +1,37 @@ package otus.homework.flowcats -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.collect class MainActivity : AppCompatActivity() { - private val diContainer = DiContainer() - private val catsViewModel by viewModels { CatsViewModelFactory(diContainer.repository) } + + private val catsViewModel by viewModels { + CatsViewModelFactory(diContainer.repository) + } 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.launch { + catsViewModel.catsState.collect { result -> + when (result) { + is Result.Success -> view.populate(result.data) + is Result.Error -> { + view.showError(result.exception.message ?: "Unknown error") + } + + Result.Loading -> { + view.showLoading() + } + } + } } } } \ No newline at end of file diff --git a/flowcats/src/main/res/layout/activity_main.xml b/flowcats/src/main/res/layout/activity_main.xml index dbcedd2f..583944d5 100644 --- a/flowcats/src/main/res/layout/activity_main.xml +++ b/flowcats/src/main/res/layout/activity_main.xml @@ -1,7 +1,9 @@ - Date: Sun, 25 Jan 2026 15:28:58 +0300 Subject: [PATCH 2/3] Task 2 --- .../otus/homework/flow/SampleInteractor.kt | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt index 1993c064..dcccc1a6 100644 --- a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt +++ b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt @@ -18,7 +18,15 @@ class SampleInteractor( * 6) возвращает результат */ fun task1(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .map { + it * 5 + }.filter { it > 20 } + .filter { it % 2 != 0 } + .take(3) + .map { + "$it won" + } } /** @@ -29,7 +37,18 @@ class SampleInteractor( * Если число не делится на 3,5,15 - эмитим само число */ fun task2(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .flatMapConcat { number -> + flow { + emit(number.toString()) + + when { + number % 15 == 0 -> emit("FizzBuzz") + number % 3 == 0 -> emit("Fizz") + number % 5 == 0 -> emit("Buzz") + } + } + } } /** @@ -38,7 +57,10 @@ class SampleInteractor( * Если айтемы в одно из флоу кончились то результирующий флоу также должен закончится */ fun task3(): Flow> { - return flowOf() + return sampleRepository.produceColors() + .zip(sampleRepository.produceForms()) { f1, f2 -> + Pair(f1, f2) + } } /** @@ -48,6 +70,14 @@ class SampleInteractor( * При любом исходе, будь то выброс исключения или успешная отработка функции вызовите метод dotsRepository.completed() */ fun task4(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .catch { e -> + if (e is IllegalArgumentException) { + emit(-1) + } else { + throw e + } + } + .onCompletion { sampleRepository.completed() } } } \ No newline at end of file From 3354d46f86d083f90035b058f35db089b9db706f Mon Sep 17 00:00:00 2001 From: Ivan Toropygin Date: Thu, 5 Feb 2026 19:32:22 +0300 Subject: [PATCH 3/3] fix --- flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt index 38267134..c782e68e 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt @@ -2,6 +2,7 @@ package otus.homework.flowcats import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flow +import kotlin.coroutines.cancellation.CancellationException class CatsRepository( private val catsService: CatsService, @@ -13,6 +14,7 @@ class CatsRepository( val latestNews = catsService.getCatFact() emit(Result.Success(latestNews)) } catch (e: Exception) { + if (e is CancellationException) throw e emit(Result.Error(e)) } delay(refreshIntervalMs)