From 64ee0de3bdb0bdf1900a5bb7da8a8aaf6edb334c Mon Sep 17 00:00:00 2001 From: Werechess Date: Thu, 19 Dec 2024 23:17:43 +0300 Subject: [PATCH] feat: homework03 --- .../otus/homework/flowcats/CatsRepository.kt | 4 +- .../java/otus/homework/flowcats/CatsView.kt | 12 ++++++ .../otus/homework/flowcats/CatsViewModel.kt | 43 +++++++++++-------- .../otus/homework/flowcats/MainActivity.kt | 15 +++++-- flowcats/src/main/res/values/strings.xml | 2 + .../otus/homework/flow/SampleInteractor.kt | 39 ++++++++++++++--- 6 files changed, 86 insertions(+), 29 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..09c16e29 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt @@ -1,7 +1,9 @@ package otus.homework.flowcats +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOn class CatsRepository( private val catsService: CatsService, @@ -14,5 +16,5 @@ class CatsRepository( emit(latestNews) delay(refreshIntervalMs) } - } + }.flowOn(Dispatchers.IO) } \ No newline at end of file diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt index 6a195f3a..cab19b18 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt @@ -3,6 +3,7 @@ package otus.homework.flowcats import android.content.Context import android.util.AttributeSet import android.widget.TextView +import android.widget.Toast import androidx.constraintlayout.widget.ConstraintLayout class CatsView @JvmOverloads constructor( @@ -11,12 +12,23 @@ class CatsView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView { + override fun load() { + findViewById(R.id.fact_textView).text = context.getText(R.string.loading) + } + override fun populate(fact: Fact) { findViewById(R.id.fact_textView).text = fact.text } + + override fun showError(message: String?) { + Toast.makeText(context, message ?: context.getText(R.string.error), Toast.LENGTH_LONG) + .show() + } } interface ICatsView { + fun load() fun populate(fact: Fact) + fun showError(message: String?) } \ 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 0d8ba8a7..2b050e95 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -1,31 +1,36 @@ package otus.homework.flowcats -import androidx.lifecycle.* -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach class CatsViewModel( - private val catsRepository: CatsRepository + catsRepository: CatsRepository ) : ViewModel() { - private val _catsLiveData = MutableLiveData() - val catsLiveData: LiveData = _catsLiveData + private val _catsFlow = MutableStateFlow(Result.Progress) + val catsFlow = _catsFlow.asStateFlow() init { - viewModelScope.launch { - withContext(Dispatchers.IO) { - catsRepository.listenForCatFacts().collect { - _catsLiveData.value = it - } - } - } + catsRepository.listenForCatFacts() + .onEach { _catsFlow.value = Result.Success(it) } + .catch { _catsFlow.value = Result.Error(it.message) } + .launchIn(viewModelScope) } } -class CatsViewModelFactory(private val catsRepository: CatsRepository) : - ViewModelProvider.NewInstanceFactory() { - override fun create(modelClass: Class): T = - CatsViewModel(catsRepository) as T +class CatsViewModelFactory(private val catsRepository: CatsRepository) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T = + modelClass.getConstructor(CatsRepository::class.java).newInstance(catsRepository) +} + +sealed class Result { + data object Progress : Result() + data class Success(val fact: Fact) : Result() + data class Error(val message: String?) : 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..e0adb0db 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt @@ -1,8 +1,11 @@ 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.flow.launchIn +import kotlinx.coroutines.flow.onEach class MainActivity : AppCompatActivity() { @@ -14,8 +17,12 @@ class MainActivity : AppCompatActivity() { val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView setContentView(view) - catsViewModel.catsLiveData.observe(this){ - view.populate(it) - } + catsViewModel.catsFlow.onEach { + when (it) { + is Result.Progress -> view.load() + is Result.Success -> view.populate(it.fact) + is Result.Error -> view.showError(it.message) + } + }.launchIn(lifecycleScope) } } \ No newline at end of file diff --git a/flowcats/src/main/res/values/strings.xml b/flowcats/src/main/res/values/strings.xml index ba737b82..c5c59365 100644 --- a/flowcats/src/main/res/values/strings.xml +++ b/flowcats/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ Flow cats + Oops! Something went wrong. + Loading… \ 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..6f040857 100644 --- a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt +++ b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt @@ -1,7 +1,14 @@ package otus.homework.flow import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.take +import kotlinx.coroutines.flow.transform +import kotlinx.coroutines.flow.zip @ExperimentalCoroutinesApi class SampleInteractor( @@ -18,7 +25,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 +41,16 @@ class SampleInteractor( * Если число не делится на 3,5,15 - эмитим само число */ fun task2(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .transform { + emit(it.toString()) + + when { + it % 15 == 0 -> emit("FizzBuzz") + it % 5 == 0 -> emit("Buzz") + it % 3 == 0 -> emit("Fizz") + } + } } /** @@ -38,7 +59,8 @@ class SampleInteractor( * Если айтемы в одно из флоу кончились то результирующий флоу также должен закончится */ fun task3(): Flow> { - return flowOf() + return sampleRepository.produceColors() + .zip(sampleRepository.produceForms()) { color, form -> color to form } } /** @@ -48,6 +70,13 @@ class SampleInteractor( * При любом исходе, будь то выброс исключения или успешная отработка функции вызовите метод dotsRepository.completed() */ fun task4(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .catch { + when (it) { + is IllegalArgumentException -> emit(-1) + else -> throw it + } + } + .onCompletion { sampleRepository.completed() } } } \ No newline at end of file