From 3dc6a9c8a017070af209ce2673bcea733e51654e Mon Sep 17 00:00:00 2001 From: Denis Date: Sat, 16 Aug 2025 18:19:05 +0300 Subject: [PATCH] flow homework --- flowcats/build.gradle | 8 +++-- flowcats/src/main/AndroidManifest.xml | 4 ++- .../otus/homework/flowcats/CatsRepository.kt | 14 ++++++-- .../otus/homework/flowcats/CatsViewModel.kt | 22 +++++++----- .../otus/homework/flowcats/MainActivity.kt | 19 ++++++++-- .../java/otus/homework/flowcats/Result.kt | 7 ++++ .../otus/homework/flow/SampleInteractor.kt | 36 ++++++++++++++++--- 7 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 flowcats/src/main/java/otus/homework/flowcats/Result.kt diff --git a/flowcats/build.gradle b/flowcats/build.gradle index 0ea35e68..aa0b1ff0 100644 --- a/flowcats/build.gradle +++ b/flowcats/build.gradle @@ -4,15 +4,16 @@ plugins { } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + compileSdkVersion 31 + buildToolsVersion "31.0.0" namespace = "otus.homework.flowcats" defaultConfig { applicationId "otus.homework.flowcats" minSdkVersion 23 - targetSdkVersion 30 + //noinspection ExpiredTargetSdkVersion + targetSdkVersion 31 versionCode 1 versionName "1.0" @@ -48,4 +49,5 @@ dependencies { implementation 'androidx.activity:activity-ktx:1.2.3' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' + implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0" } \ No newline at end of file diff --git a/flowcats/src/main/AndroidManifest.xml b/flowcats/src/main/AndroidManifest.xml index 2deb6454..d57e0372 100644 --- a/flowcats/src/main/AndroidManifest.xml +++ b/flowcats/src/main/AndroidManifest.xml @@ -10,7 +10,9 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Flow" > - + diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt index 10fcb77d..9b962709 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt @@ -1,5 +1,6 @@ package otus.homework.flowcats +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flow @@ -10,8 +11,17 @@ class CatsRepository( fun listenForCatFacts() = flow { while (true) { - val latestNews = catsService.getCatFact() - emit(latestNews) + try { + val latestNews = catsService.getCatFact() + emit(Result.Success(latestNews)) + } catch (e: Exception) { + if (e is CancellationException) throw e + e.printStackTrace() + // так как сервис не доступен, я хз почему приложение по задумке должно было крашится, + // но у меня оно крашилось из-за 503 от сервера + emit(Result.Error) + } + delay(refreshIntervalMs) } } diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index 0d8ba8a7..531fd2fd 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -2,7 +2,11 @@ package otus.homework.flowcats import androidx.lifecycle.* import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -10,15 +14,17 @@ class CatsViewModel( private val catsRepository: CatsRepository ) : ViewModel() { - private val _catsLiveData = MutableLiveData() - val catsLiveData: LiveData = _catsLiveData + private val _catsFlow = MutableStateFlow(Result.Loading) + val catsFlow: StateFlow = _catsFlow.asStateFlow() init { viewModelScope.launch { withContext(Dispatchers.IO) { - catsRepository.listenForCatFacts().collect { - _catsLiveData.value = it - } + catsRepository.listenForCatFacts() + .onEach { + _catsFlow.emit(it) + } + .launchIn(viewModelScope) } } } @@ -26,6 +32,6 @@ class CatsViewModel( class CatsViewModelFactory(private val catsRepository: CatsRepository) : ViewModelProvider.NewInstanceFactory() { - override fun create(modelClass: Class): T = + override fun create(modelClass: Class): T = 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..723772dc 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt @@ -3,6 +3,11 @@ package otus.homework.flowcats import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.activity.viewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { @@ -13,9 +18,17 @@ class MainActivity : AppCompatActivity() { 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 { + repeatOnLifecycle(Lifecycle.State.STARTED) { + catsViewModel.catsFlow.onEach { result -> + when (result) { + is Result.Success -> view.populate(result.uiModel) + else -> { + // не было сказано в задании как обрабатывать + } + } + } + } } } } \ No newline at end of file diff --git a/flowcats/src/main/java/otus/homework/flowcats/Result.kt b/flowcats/src/main/java/otus/homework/flowcats/Result.kt new file mode 100644 index 00000000..1f12fdb9 --- /dev/null +++ b/flowcats/src/main/java/otus/homework/flowcats/Result.kt @@ -0,0 +1,7 @@ +package otus.homework.flowcats + +sealed interface Result { + data class Success(val uiModel: Fact) : Result + data object Error : Result + data object Loading : Result +} \ 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..222c26d0 100644 --- a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt +++ b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt @@ -18,7 +18,12 @@ class SampleInteractor( * 6) возвращает результат */ fun task1(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .map { it * 5 } + .filter { it > 20 } + .filter { it % 2 != 0 } + .map { "$it won" } + .take(3) } /** @@ -29,7 +34,17 @@ class SampleInteractor( * Если число не делится на 3,5,15 - эмитим само число */ fun task2(): Flow { - return flowOf() + return sampleRepository.produceNumbers().transform { value -> + emit(value.toString()) + val isDivisibleBy3 = value % 3 == 0 + val isDivisibleBy5 = value % 5 == 0 + val isDivisibleBy15 = isDivisibleBy3 && isDivisibleBy5 + when { + isDivisibleBy15 -> emit("FizzBuzz") + isDivisibleBy3 -> emit("Fizz") + isDivisibleBy5 -> emit("Buzz") + } + } } /** @@ -38,7 +53,10 @@ class SampleInteractor( * Если айтемы в одно из флоу кончились то результирующий флоу также должен закончится */ fun task3(): Flow> { - return flowOf() + return sampleRepository.produceColors() + .zip(sampleRepository.produceForms()) { color, form -> + Pair(color, form) + } } /** @@ -48,6 +66,16 @@ class SampleInteractor( * При любом исходе, будь то выброс исключения или успешная отработка функции вызовите метод dotsRepository.completed() */ fun task4(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .catch { + if (it is IllegalArgumentException) { + emit(-1) + } else { + throw it + } + } + .onCompletion { + sampleRepository.completed() + } } } \ No newline at end of file