From e7b52e38fb35b9c1f3ee605cc7cea4afadf62805 Mon Sep 17 00:00:00 2001 From: Vitaliy Farsiyan Date: Sat, 22 Oct 2022 15:23:21 +0300 Subject: [PATCH 1/4] change from value to post value livedata --- flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index 0d8ba8a7..e0109fc3 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -17,7 +17,7 @@ class CatsViewModel( viewModelScope.launch { withContext(Dispatchers.IO) { catsRepository.listenForCatFacts().collect { - _catsLiveData.value = it + _catsLiveData.postValue(it) } } } From 098ea104b4ea88ec4baecfdea7cb86b1971a54e8 Mon Sep 17 00:00:00 2001 From: Vitaliy Farsiyan Date: Sat, 22 Oct 2022 17:37:04 +0300 Subject: [PATCH 2/4] set stateflow and add Result State --- flowcats/src/main/java/otus/homework/flowcats/Result.kt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 flowcats/src/main/java/otus/homework/flowcats/Result.kt 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..17d7339d --- /dev/null +++ b/flowcats/src/main/java/otus/homework/flowcats/Result.kt @@ -0,0 +1,3 @@ +package otus.homework.flowcats + +sealed class Result From 0b2e6799ebb5be1b73631be82e2974fe5d4a4e5f Mon Sep 17 00:00:00 2001 From: Vitaliy Farsiyan Date: Tue, 25 Oct 2022 15:01:46 +0300 Subject: [PATCH 3/4] flow homework completed --- flowcats/build.gradle | 3 +- .../otus/homework/flowcats/CatsViewModel.kt | 20 +++++++-- .../otus/homework/flowcats/MainActivity.kt | 17 ++++++- .../java/otus/homework/flowcats/Result.kt | 6 ++- .../homework/flow/ExampleInstrumentedTest.kt | 44 +++++++++---------- .../otus/homework/flow/SampleInteractor.kt | 41 +++++++++++++++-- .../homework/flow/SampleInteractorTest.kt | 11 +++-- 7 files changed, 102 insertions(+), 40 deletions(-) diff --git a/flowcats/build.gradle b/flowcats/build.gradle index cefa21e0..16ae23aa 100644 --- a/flowcats/build.gradle +++ b/flowcats/build.gradle @@ -45,5 +45,6 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3' 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-viewmodel-ktx:2.5.1' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.0-alpha02' } \ 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 e0109fc3..ccaec0be 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -2,6 +2,8 @@ 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.collect import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -13,11 +15,20 @@ class CatsViewModel( private val _catsLiveData = MutableLiveData() val catsLiveData: LiveData = _catsLiveData + private val _catsStateFlow = MutableStateFlow>(Result.Success(null)) + val catsStateFlow: StateFlow> = _catsStateFlow + init { viewModelScope.launch { withContext(Dispatchers.IO) { - catsRepository.listenForCatFacts().collect { - _catsLiveData.postValue(it) + try { + catsRepository.listenForCatFacts().collect { + _catsStateFlow.value = Result.Success(it) + } + } catch (e: Exception) { + catsRepository.listenForCatFacts().collect { + _catsStateFlow.value = Result.Error(it) + } } } } @@ -26,6 +37,7 @@ class CatsViewModel( 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..e1ce483a 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.launch +import kotlin.math.log class MainActivity : AppCompatActivity() { @@ -14,8 +19,16 @@ class MainActivity : AppCompatActivity() { val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView setContentView(view) - catsViewModel.catsLiveData.observe(this){ - view.populate(it) +// catsViewModel.catsLiveData.observe(this){ +// view.populate(it) +// } + + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + catsViewModel.catsStateFlow.collect { + it.data?.let { fact -> view.populate(fact) } + } + } } } } \ 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 index 17d7339d..dc9c0c0c 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/Result.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/Result.kt @@ -1,3 +1,7 @@ package otus.homework.flowcats -sealed class Result + +sealed class Result(val data:T? = null) { + class Success(data: T?): Result(data) + class Error(data: T?): Result(data) +} diff --git a/operators/src/androidTest/java/otus/homework/flow/ExampleInstrumentedTest.kt b/operators/src/androidTest/java/otus/homework/flow/ExampleInstrumentedTest.kt index 2a37f840..10b1d664 100644 --- a/operators/src/androidTest/java/otus/homework/flow/ExampleInstrumentedTest.kt +++ b/operators/src/androidTest/java/otus/homework/flow/ExampleInstrumentedTest.kt @@ -1,24 +1,24 @@ package otus.homework.flow -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("otus.homework.flow", appContext.packageName) - } -} \ No newline at end of file +//import androidx.test.platform.app.InstrumentationRegistry +//import androidx.test.ext.junit.runners.AndroidJUnit4 +// +//import org.junit.Test +//import org.junit.runner.RunWith +// +//import org.junit.Assert.* +// +///** +// * Instrumented test, which will execute on an Android device. +// * +// * See [testing documentation](http://d.android.com/tools/testing). +// */ +//@RunWith(AndroidJUnit4::class) +//class ExampleInstrumentedTest { +// @Test +// fun useAppContext() { +// // Context of the app under test. +// val appContext = InstrumentationRegistry.getInstrumentation().targetContext +// assertEquals("otus.homework.flow", appContext.packageName) +// } +//} \ 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..c1becf6d 100644 --- a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt +++ b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt @@ -18,7 +18,18 @@ class SampleInteractor( * 6) возвращает результат */ fun task1(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .map { element -> + element * 5 + } + .filter { element -> + element > 20 + element % 2 != 0 + } + .map { element -> + "$element won" + } + .take(3) } /** @@ -29,7 +40,18 @@ class SampleInteractor( * Если число не делится на 3,5,15 - эмитим само число */ fun task2(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .map { element -> + if (element % 15 == 0) { + "$element, FizzBuzz" + } else if(element % 3 == 0) { + "$element, Fizz" + } else if (element % 5 == 0) { + "$element, Buzz" + } else { + element.toString() + } + } } /** @@ -38,7 +60,9 @@ class SampleInteractor( * Если айтемы в одно из флоу кончились то результирующий флоу также должен закончится */ fun task3(): Flow> { - return flowOf() + return sampleRepository.produceColors().zip(sampleRepository.produceForms()) { firstFlow, secondFlow -> + Pair(firstFlow, secondFlow) + } } /** @@ -48,6 +72,15 @@ class SampleInteractor( * При любом исходе, будь то выброс исключения или успешная отработка функции вызовите метод dotsRepository.completed() */ fun task4(): Flow { - return flowOf() + return flow { + sampleRepository.produceNumbers().catch { + if (it is IllegalArgumentException) emit(-1) + else throw it + }.onCompletion { + sampleRepository.completed() + }.collect { + emit(it) + } + } } } \ No newline at end of file diff --git a/operators/src/test/java/otus/homework/flow/SampleInteractorTest.kt b/operators/src/test/java/otus/homework/flow/SampleInteractorTest.kt index 0f26255f..d38f83d8 100644 --- a/operators/src/test/java/otus/homework/flow/SampleInteractorTest.kt +++ b/operators/src/test/java/otus/homework/flow/SampleInteractorTest.kt @@ -1,17 +1,16 @@ package otus.homework.flow +import io.mockk.InternalPlatformDsl.toArray import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.flow.* import kotlinx.coroutines.test.runBlockingTest import org.junit.Assert.assertEquals import org.junit.Assert.assertThrows import org.junit.Test +import java.util.* @ExperimentalCoroutinesApi @@ -65,8 +64,7 @@ class SampleInteractorTest { "20", "Buzz", "21", - "Fizz" - ) + "Fizz") val actual = dotsInteractor.task2().toList() assertEquals(expected, actual) @@ -84,6 +82,7 @@ class SampleInteractorTest { every { dotsRepository.produceForms() } returns flowOf("Circle", "Square", "Triangle") val expected = listOf("Red" to "Circle", "Green" to "Square", "Blue" to "Triangle") + val actual = dotsInteractor.task3().toList() assertEquals(expected, actual) From 9a43b73964eab378ee5e7729c0ce8d312b587be7 Mon Sep 17 00:00:00 2001 From: Vitaliy Farsiyan Date: Tue, 29 Nov 2022 14:57:43 +0300 Subject: [PATCH 4/4] fixed dispatcher flow --- flowcats/build.gradle | 2 +- .../src/main/java/otus/homework/flowcats/CatsRepository.kt | 4 +++- .../src/main/java/otus/homework/flowcats/CatsViewModel.kt | 2 +- operators/build.gradle | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/flowcats/build.gradle b/flowcats/build.gradle index 16ae23aa..205962f7 100644 --- a/flowcats/build.gradle +++ b/flowcats/build.gradle @@ -46,5 +46,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.5.1' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.0-alpha02' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' } \ No newline at end of file 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/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index ccaec0be..cc5e8b6a 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -20,7 +20,7 @@ class CatsViewModel( init { viewModelScope.launch { - withContext(Dispatchers.IO) { + withContext(Dispatchers.Main) { try { catsRepository.listenForCatFacts().collect { _catsStateFlow.value = Result.Success(it) diff --git a/operators/build.gradle b/operators/build.gradle index 39c4b952..a35f74e3 100644 --- a/operators/build.gradle +++ b/operators/build.gradle @@ -38,5 +38,5 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3' 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-viewmodel-ktx:2.5.1' } \ No newline at end of file