From 0b8679345997316c648779ab6e60d8f8e2c98f99 Mon Sep 17 00:00:00 2001 From: Ruslan Sabirov Date: Sat, 17 Jan 2026 22:38:22 +0300 Subject: [PATCH 1/3] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B8=D0=BB=20RxJava2=20=D0=BA=20Retrofit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/otus/homework/reactivecats/CatsService.kt | 4 ++-- gradle/libs.versions.toml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/otus/homework/reactivecats/CatsService.kt b/app/src/main/java/otus/homework/reactivecats/CatsService.kt index f30b3aa..89c3287 100644 --- a/app/src/main/java/otus/homework/reactivecats/CatsService.kt +++ b/app/src/main/java/otus/homework/reactivecats/CatsService.kt @@ -1,11 +1,11 @@ package otus.homework.reactivecats -import retrofit2.Call +import io.reactivex.Single import retrofit2.http.GET interface CatsService { //@GET("random?animal_type=cat") @GET("fact") - fun getCatFact(): Call + fun getCatFact(): Single } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 46c9578..728dc23 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -30,12 +30,13 @@ okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhtt okhttp-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" } picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" } retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } +retrofit-rxjava = { group = "com.squareup.retrofit2", name = "adapter-rxjava2", version.ref = "retrofit" } retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" } rxandroid = { module = "io.reactivex.rxjava2:rxandroid", version.ref = "rxandroid" } rxjava = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxjava" } [bundles] -network = ["okhttp", "okhttp-logging-interceptor", "retrofit", "retrofit-converter-gson"] +network = ["okhttp", "okhttp-logging-interceptor", "retrofit", "retrofit-converter-gson", "retrofit-rxjava"] [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } From f8ee969a2e829c273941926514b5506ea1e37ca3 Mon Sep 17 00:00:00 2001 From: Ruslan Sabirov Date: Sat, 17 Jan 2026 23:48:26 +0300 Subject: [PATCH 2/3] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BB=20LocalCatFactsGenerator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reactivecats/LocalCatFactsGenerator.kt | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt b/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt index 4481062..8dcfe03 100644 --- a/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt +++ b/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt @@ -3,28 +3,30 @@ 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( private val context: Context ) { - /** - * Реализуйте функцию otus.homework.reactivecats.LocalCatFactsGenerator#generateCatFact так, - * чтобы она возвращала Fact со случайной строкой из массива строк R.array.local_cat_facts - * обернутую в подходящий стрим(Flowable/Single/Observable и т.п) - */ fun generateCatFact(): Single { - return Single.never() + return Single.just(newCatFact()) } - /** - * Реализуйте функцию otus.homework.reactivecats.LocalCatFactsGenerator#generateCatFactPeriodically так, - * чтобы она эмитила Fact со случайной строкой из массива строк R.array.local_cat_facts каждые 2000 миллисекунд. - * Если вновь заэмиченный Fact совпадает с предыдущим - пропускаем элемент. - */ fun generateCatFactPeriodically(): Flowable { - val success = Fact(context.resources.getStringArray(R.array.local_cat_facts)[Random.nextInt(5)]) - return Flowable.empty() + return Flowable.interval(2000, TimeUnit.MILLISECONDS) + .map { + newCatFact() + } + .distinctUntilChanged { oldFact, newFact -> + oldFact.fact == newFact.fact + } + } + + private fun newCatFact(): Fact { + val factsArray = context.resources.getStringArray(R.array.local_cat_facts) + val randomIndex = Random.nextInt(factsArray.size) + return Fact(factsArray[randomIndex]) } } \ No newline at end of file From 117b887fbb9c7ffdfe929d962b71213ad66d68f7 Mon Sep 17 00:00:00 2001 From: Ruslan Sabirov Date: Sun, 18 Jan 2026 00:51:58 +0300 Subject: [PATCH 3/3] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BB=20CatsViewModel=20=D0=BD=D0=B0=20RxJava?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../homework/reactivecats/CatsViewModel.kt | 55 +++++++++++++------ .../otus/homework/reactivecats/DiContainer.kt | 2 + .../homework/reactivecats/MainActivity.kt | 1 + 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt index d62eaf9..c372bde 100644 --- a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt +++ b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt @@ -5,40 +5,59 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import io.reactivex.Flowable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.schedulers.Schedulers import retrofit2.Call import retrofit2.Callback import retrofit2.Response +import java.util.concurrent.TimeUnit class CatsViewModel( - catsService: CatsService, - localCatFactsGenerator: LocalCatFactsGenerator, - context: Context + private val catsService: CatsService, + private val localCatFactsGenerator: LocalCatFactsGenerator, + private val context: Context ) : ViewModel() { 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 { + private val compositeDisposable = CompositeDisposable() + + fun getFacts() { + compositeDisposable.clear() + + val disposable = Flowable.interval(2000, TimeUnit.MILLISECONDS) + .flatMapSingle { _ -> + catsService.getCatFact() + .subscribeOn(Schedulers.io()) + .onErrorResumeNext { throwable -> + localCatFactsGenerator.generateCatFact() + .subscribeOn(Schedulers.io()) + } + } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { fact -> + _catsLiveData.value = Success(fact) + }, + { error -> _catsLiveData.value = Error( - response.errorBody()?.string() ?: context.getString( - R.string.default_error_text - ) + error.message ?: context.getString(R.string.default_error_text) ) } - } + ) - override fun onFailure(call: Call, t: Throwable) { - _catsLiveData.value = ServerError - } - }) + compositeDisposable.add(disposable) + } + + override fun onCleared() { + super.onCleared() + compositeDisposable.clear() } - fun getFacts() {} } class CatsViewModelFactory( diff --git a/app/src/main/java/otus/homework/reactivecats/DiContainer.kt b/app/src/main/java/otus/homework/reactivecats/DiContainer.kt index bbccfc7..41d4e3e 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 { @@ -11,6 +12,7 @@ class DiContainer { //.baseUrl("https://cat-fact.herokuapp.com/facts/") .baseUrl("https://catfact.ninja/") .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() } diff --git a/app/src/main/java/otus/homework/reactivecats/MainActivity.kt b/app/src/main/java/otus/homework/reactivecats/MainActivity.kt index 8ec9571..78e86fd 100644 --- a/app/src/main/java/otus/homework/reactivecats/MainActivity.kt +++ b/app/src/main/java/otus/homework/reactivecats/MainActivity.kt @@ -22,6 +22,7 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView setContentView(view) + catsViewModel.getFacts() catsViewModel.catsLiveData.observe(this) { result -> when (result) { is Success -> view.populate(result.fact)