diff --git a/flowcats/build.gradle b/flowcats/build.gradle index 0ea35e68..5eccf2fa 100644 --- a/flowcats/build.gradle +++ b/flowcats/build.gradle @@ -4,15 +4,15 @@ plugins { } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + compileSdkVersion 36 + buildToolsVersion "34.0.0" namespace = "otus.homework.flowcats" defaultConfig { applicationId "otus.homework.flowcats" minSdkVersion 23 - targetSdkVersion 30 + targetSdkVersion 33 versionCode 1 versionName "1.0" @@ -46,6 +46,7 @@ dependencies { implementation 'com.squareup.picasso:picasso:2.71828' 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-runtime-ktx:2.9.4' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3' } \ No newline at end of file diff --git a/flowcats/src/main/AndroidManifest.xml b/flowcats/src/main/AndroidManifest.xml index 2deb6454..6531e25f 100644 --- a/flowcats/src/main/AndroidManifest.xml +++ b/flowcats/src/main/AndroidManifest.xml @@ -10,7 +10,8 @@ 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..c0948b86 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsRepository.kt @@ -10,8 +10,12 @@ class CatsRepository( fun listenForCatFacts() = flow { while (true) { - val latestNews = catsService.getCatFact() - emit(latestNews) + try { + val fact = catsService.getCatFact() + emit(Result.Success(fact)) + } catch (e: Exception) { + emit(Result.Error(e)) + } delay(refreshIntervalMs) } } diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsService.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsService.kt index 25192882..787829a1 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsService.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsService.kt @@ -4,6 +4,6 @@ import retrofit2.http.GET interface CatsService { - @GET("random?animal_type=cat") + @GET("fact") suspend fun getCatFact(): Fact } \ 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..eba22638 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsView.kt @@ -12,7 +12,7 @@ class CatsView @JvmOverloads constructor( ) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView { override fun populate(fact: Fact) { - findViewById(R.id.fact_textView).text = fact.text + findViewById(R.id.fact_textView).text = fact.fact } } diff --git a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt index 0d8ba8a7..8d29ea5e 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/CatsViewModel.kt @@ -2,7 +2,12 @@ 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.catch import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -10,15 +15,16 @@ class CatsViewModel( private val catsRepository: CatsRepository ) : ViewModel() { - private val _catsLiveData = MutableLiveData() - val catsLiveData: LiveData = _catsLiveData + private val _catsStateFlow = MutableStateFlow(null) + val catsStateFlow: StateFlow = _catsStateFlow.asStateFlow() init { viewModelScope.launch { withContext(Dispatchers.IO) { - catsRepository.listenForCatFacts().collect { - _catsLiveData.value = it - } + catsRepository.listenForCatFacts() + .collect { result -> + _catsStateFlow.value = result + } } } } @@ -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/DiContainer.kt b/flowcats/src/main/java/otus/homework/flowcats/DiContainer.kt index 485152e2..479958b5 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/DiContainer.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/DiContainer.kt @@ -7,7 +7,7 @@ class DiContainer { private val retrofit by lazy { Retrofit.Builder() - .baseUrl("https://cat-fact.herokuapp.com/facts/") + .baseUrl("https://catfact.ninja/") .addConverterFactory(GsonConverterFactory.create()) .build() } diff --git a/flowcats/src/main/java/otus/homework/flowcats/Fact.kt b/flowcats/src/main/java/otus/homework/flowcats/Fact.kt index 602303eb..ced6adcc 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/Fact.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/Fact.kt @@ -3,22 +3,6 @@ package otus.homework.flowcats import com.google.gson.annotations.SerializedName data class Fact( - @field:SerializedName("createdAt") - val createdAt: String, - @field:SerializedName("deleted") - val deleted: Boolean, - @field:SerializedName("_id") - val id: String, - @field:SerializedName("text") - val text: String, - @field:SerializedName("source") - val source: String, - @field:SerializedName("used") - val used: Boolean, - @field:SerializedName("type") - val type: String, - @field:SerializedName("user") - val user: String, - @field:SerializedName("updatedAt") - val updatedAt: String + @field:SerializedName("fact") + val fact: String ) \ 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..820f40d0 100644 --- a/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt +++ b/flowcats/src/main/java/otus/homework/flowcats/MainActivity.kt @@ -1,8 +1,14 @@ package otus.homework.flowcats -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.widget.Toast import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch +import androidx.lifecycle.repeatOnLifecycle class MainActivity : AppCompatActivity() { @@ -14,8 +20,19 @@ class MainActivity : AppCompatActivity() { 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.catsStateFlow.collect { result -> + result?.let { + when (it) { + is Result.Success<*> -> view.populate(it.data as Fact) + is Result.Error -> { + Toast.makeText(this@MainActivity, it.ex.message, Toast.LENGTH_SHORT).show() + } + } + } + } + } } } } \ 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..f890d8f2 --- /dev/null +++ b/flowcats/src/main/java/otus/homework/flowcats/Result.kt @@ -0,0 +1,6 @@ +package otus.homework.flowcats + +sealed class Result { + data class Success(val data: T) : Result() + data class Error(val ex: Throwable) : 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..95fbce6b 100644 --- a/operators/src/main/java/otus/homework/flow/SampleInteractor.kt +++ b/operators/src/main/java/otus/homework/flow/SampleInteractor.kt @@ -18,7 +18,16 @@ class SampleInteractor( * 6) возвращает результат */ fun task1(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .map { + it.times(5) + }.filter { + it > 20 + }.filter { + it % 2 != 0 + }.map { + "$it won" + }.take(3) } /** @@ -29,7 +38,27 @@ class SampleInteractor( * Если число не делится на 3,5,15 - эмитим само число */ fun task2(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .transform { + when { + it % 15 == 0 -> { + emit(it.toString()) + emit("FizzBuzz") + } + + it % 3 == 0 -> { + emit(it.toString()) + emit("Fizz") + } + + it % 5 == 0 -> { + emit(it.toString()) + emit("Buzz") + } + + else -> emit(it.toString()) + } + } } /** @@ -38,7 +67,10 @@ class SampleInteractor( * Если айтемы в одно из флоу кончились то результирующий флоу также должен закончится */ fun task3(): Flow> { - return flowOf() + return sampleRepository.produceColors() + .zip(sampleRepository.produceForms()) { color, form -> + Pair(color, form) + } } /** @@ -48,6 +80,15 @@ class SampleInteractor( * При любом исходе, будь то выброс исключения или успешная отработка функции вызовите метод dotsRepository.completed() */ fun task4(): Flow { - return flowOf() + return sampleRepository.produceNumbers() + .catch { exception -> + if (exception is IllegalArgumentException) { + emit(-1) } else { + throw exception + } + } + .onCompletion { + sampleRepository.completed() + } } } \ No newline at end of file