diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt index 10fcb77d..786dd7ee 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt @@ -1,7 +1,10 @@ package otus.homework.flowcats +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOn +import kotlin.coroutines.cancellation.CancellationException class CatsRepository( private val catsService: CatsService, @@ -10,9 +13,15 @@ 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 + emit(Result.Error(e.message.orEmpty())) + } 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..fadf120c 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( @@ -14,9 +15,16 @@ class CatsView @JvmOverloads constructor( override fun populate(fact: Fact) { findViewById(R.id.fact_textView).text = fact.text } + + override fun showToast(text: String) { + if (text.isNotEmpty()) { + Toast.makeText(context, text, Toast.LENGTH_SHORT).show() + } + } } interface ICatsView { fun populate(fact: Fact) + fun showToast(text: 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..b544031b 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -1,24 +1,23 @@ package otus.homework.flowcats import androidx.lifecycle.* -import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collect 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 _state = MutableStateFlow>(Result.None) + internal val state: StateFlow> = _state.asStateFlow() init { viewModelScope.launch { - withContext(Dispatchers.IO) { - catsRepository.listenForCatFacts().collect { - _catsLiveData.value = it - } + catsRepository.listenForCatFacts().collect { + _state.value = it } } } @@ -26,6 +25,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..083e983f 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt @@ -3,19 +3,44 @@ package otus.homework.flowcats import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.activity.viewModels +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { private val diContainer = DiContainer() private val catsViewModel by viewModels { CatsViewModelFactory(diContainer.repository) } + private var job: Job? = null + private lateinit var view: CatsView + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView + view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView setContentView(view) + } - catsViewModel.catsLiveData.observe(this){ - view.populate(it) + override fun onStart() { + super.onStart() + job = lifecycleScope.launch { + catsViewModel.state.collect { result -> + when (result) { + is Result.Success -> { + view.populate(result.data) + } + is Result.Error -> { + view.showToast(result.errorMsg) + } + else -> {} + } + } } } + + override fun onStop() { + super.onStop() + job?.cancel() + } } \ 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..68e7359a --- /dev/null +++ b/flowcats/src/main/java/otus/homework/flowcats/Result.kt @@ -0,0 +1,7 @@ +package otus.homework.flowcats + +sealed class Result { + object None: Result() + data class Success(val data: T) : Result() + data class Error(val errorMsg: String) : 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..6514eb43 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,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 +60,10 @@ class SampleInteractor( * Если айтемы в одно из флоу кончились то результирующий флоу также должен закончится */ fun task3(): Flow> { - return flowOf() + return sampleRepository.produceColors() + .zip(sampleRepository.produceForms()) { color, form -> + Pair(color, form) + } } /** @@ -48,6 +73,15 @@ class SampleInteractor( * При любом исходе, будь то выброс исключения или успешная отработка функции вызовите метод dotsRepository.completed() */ fun task4(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .catch { e -> + when (e) { + is IllegalArgumentException -> emit(-1) + else -> throw e + } + } + .onCompletion { + sampleRepository.completed() + } } } \ No newline at end of file