From 90010fba2a9d0ab4ce74d45ec815319496ec64c1 Mon Sep 17 00:00:00 2001 From: Pavel Semin Date: Mon, 14 Apr 2025 21:30:02 +0300 Subject: [PATCH] homework number one completed --- app/build.gradle | 1 + .../otus/homework/reactivecats/CatsService.kt | 4 +- .../homework/reactivecats/CatsViewModel.kt | 77 +++++++++++++------ .../otus/homework/reactivecats/DiContainer.kt | 2 + .../reactivecats/LocalCatFactsGenerator.kt | 12 ++- .../homework/reactivecats/MainActivity.kt | 1 - 6 files changed, 67 insertions(+), 30 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 71df92dd..315f1a80 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation 'androidx.core:core-ktx:1.12.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0' implementation 'com.google.code.gson:gson:2.10' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.11.0' diff --git a/app/src/main/java/otus/homework/reactivecats/CatsService.kt b/app/src/main/java/otus/homework/reactivecats/CatsService.kt index c79be483..17d1e38e 100644 --- a/app/src/main/java/otus/homework/reactivecats/CatsService.kt +++ b/app/src/main/java/otus/homework/reactivecats/CatsService.kt @@ -1,10 +1,10 @@ package otus.homework.reactivecats -import retrofit2.Call +import io.reactivex.Single import retrofit2.http.GET interface CatsService { @GET("random?animal_type=cat") - fun getCatFact(): Call + fun getCatFact(): Single } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt index d62eaf97..18ea3848 100644 --- a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt +++ b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt @@ -5,40 +5,69 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import io.reactivex.schedulers.Schedulers +import retrofit2.HttpException class CatsViewModel( - catsService: CatsService, - localCatFactsGenerator: LocalCatFactsGenerator, + private val catsService: CatsService, + private val localCatFactsGenerator: LocalCatFactsGenerator, context: Context ) : ViewModel() { + private val errorMsg = context.getString(R.string.default_error_text) + private val compositeDisposable = CompositeDisposable() private val _catsLiveData = MutableLiveData() val catsLiveData: LiveData = _catsLiveData init { - catsService.getCatFact().enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful && response.body() != null) { - _catsLiveData.value = Success(response.body()!!) - } else { - _catsLiveData.value = Error( - response.errorBody()?.string() ?: context.getString( - R.string.default_error_text - ) - ) - } - } - - override fun onFailure(call: Call, t: Throwable) { - _catsLiveData.value = ServerError - } - }) + getFacts() + } + + override fun onCleared() { + super.onCleared() + compositeDisposable.clear() + } + + private fun getFacts() { + catsService.getCatFact() + .onErrorResumeNext { localCatFactsGenerator.generateCatFact() } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + ::handleSuccess, + ::handleError + ).let(::addToCompositeDisposable) + } + + private fun getFactPeriodically() { + localCatFactsGenerator.generateCatFactPeriodically() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + ::handleSuccess, + ::handleError + ).let(::addToCompositeDisposable) } - fun getFacts() {} + + private fun handleSuccess(fact: Fact) { + _catsLiveData.value = Success(fact) + } + + private fun handleError(error: Throwable) { + _catsLiveData.value = if (error is HttpException) { + ServerError + } else { + Error(error.message ?: errorMsg) + } + } + + private fun addToCompositeDisposable(disposable: Disposable) { + compositeDisposable.add(disposable) + } } class CatsViewModelFactory( @@ -55,4 +84,4 @@ class CatsViewModelFactory( sealed class Result data class Success(val fact: Fact) : Result() data class Error(val message: String) : Result() -object ServerError : Result() \ No newline at end of file +data object ServerError : Result() \ No newline at end of file diff --git a/app/src/main/java/otus/homework/reactivecats/DiContainer.kt b/app/src/main/java/otus/homework/reactivecats/DiContainer.kt index dfbb9a2b..ad1aa751 100644 --- a/app/src/main/java/otus/homework/reactivecats/DiContainer.kt +++ b/app/src/main/java/otus/homework/reactivecats/DiContainer.kt @@ -2,6 +2,7 @@ package otus.homework.reactivecats import android.content.Context import retrofit2.Retrofit +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.converter.gson.GsonConverterFactory class DiContainer { @@ -10,6 +11,7 @@ class DiContainer { Retrofit.Builder() .baseUrl("https://cat-fact.herokuapp.com/facts/") .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() } diff --git a/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt b/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt index 4481062e..bee75654 100644 --- a/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt +++ b/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt @@ -3,6 +3,7 @@ package otus.homework.reactivecats import android.content.Context import io.reactivex.Flowable import io.reactivex.Single +import java.util.concurrent.TimeUnit import kotlin.random.Random class LocalCatFactsGenerator( @@ -15,7 +16,7 @@ class LocalCatFactsGenerator( * обернутую в подходящий стрим(Flowable/Single/Observable и т.п) */ fun generateCatFact(): Single { - return Single.never() + return Single.fromCallable { getRandomFact() } } /** @@ -24,7 +25,12 @@ class LocalCatFactsGenerator( * Если вновь заэмиченный Fact совпадает с предыдущим - пропускаем элемент. */ fun generateCatFactPeriodically(): Flowable { - val success = Fact(context.resources.getStringArray(R.array.local_cat_facts)[Random.nextInt(5)]) - return Flowable.empty() + return Flowable.interval(0, 2000, TimeUnit.MILLISECONDS) + .map { getRandomFact() } + .distinctUntilChanged() + } + + private fun getRandomFact(): Fact { + return Fact(context.resources.getStringArray(R.array.local_cat_facts)[Random.nextInt(5)]) } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/reactivecats/MainActivity.kt b/app/src/main/java/otus/homework/reactivecats/MainActivity.kt index 8ec95711..b5d72a5b 100644 --- a/app/src/main/java/otus/homework/reactivecats/MainActivity.kt +++ b/app/src/main/java/otus/homework/reactivecats/MainActivity.kt @@ -4,7 +4,6 @@ import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Toast import androidx.activity.viewModels -import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar class MainActivity : AppCompatActivity() {