From ba99f4145083a297878f75a335ff53411809e915 Mon Sep 17 00:00:00 2001 From: Beknur Patsaev Date: Mon, 3 Feb 2025 00:53:19 +0300 Subject: [PATCH 1/5] =?UTF-8?q?1.=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B2=D0=B5?= =?UTF-8?q?=D0=B4=D0=B8=D1=82=D0=B5=20=D1=81=D0=B5=D1=82=D0=B5=D0=B2=D0=BE?= =?UTF-8?q?=D0=B9=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=20=D1=81=20`retro?= =?UTF-8?q?fit.Call`=20=D0=BD=D0=B0=20RX=20=D1=86=D0=B5=D0=BF=D0=BE=D1=87?= =?UTF-8?q?=D0=BA=D1=83.=20=D0=94=D0=BB=D1=8F=20=D1=8D=D1=82=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=20Retrofit=20=D0=B0=D0=B4=D0=B0=D0=BF=D1=82=D0=B5=D1=80,?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BC=D0=B5=D0=BD=D1=8F=D0=B9=D1=82=D0=B5=20?= =?UTF-8?q?=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=89=D0=B0=D0=B5=D0=BC?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=82=D0=B8=D0=BF=D1=8B=20=D1=84=D1=83=D0=BD?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 1 + .../otus/homework/reactivecats/CatsService.kt | 4 +-- .../homework/reactivecats/CatsViewModel.kt | 32 ++++++++----------- .../otus/homework/reactivecats/DiContainer.kt | 2 ++ 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 71df92dd..0249fbb8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -46,4 +46,5 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0' implementation "io.reactivex.rxjava2:rxjava:2.2.21" implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' + implementation("com.squareup.retrofit2:adapter-rxjava2:2.7.1") } \ No newline at end of file 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..e3449aad 100644 --- a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt +++ b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt @@ -5,37 +5,33 @@ 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.schedulers.Schedulers class CatsViewModel( catsService: CatsService, localCatFactsGenerator: LocalCatFactsGenerator, context: Context ) : ViewModel() { + 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 { + compositeDisposable.addAll( + catsService.getCatFact() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ fact -> + _catsLiveData.value = Success(fact) + }, { _catsLiveData.value = Error( - response.errorBody()?.string() ?: context.getString( - R.string.default_error_text - ) + it?.message.toString() ) - } - } - - override fun onFailure(call: Call, t: Throwable) { - _catsLiveData.value = ServerError - } - }) + }) + ) } fun getFacts() {} 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() } From 3bc2d76be093b692ae07b103f751e28b178e109e Mon Sep 17 00:00:00 2001 From: Beknur Patsaev Date: Mon, 3 Feb 2025 00:59:00 +0300 Subject: [PATCH 2/5] =?UTF-8?q?2.=20=D0=9F=D0=BE=D0=BC=D0=B5=D0=BD=D1=8F?= =?UTF-8?q?=D0=B9=D1=82=D0=B5=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D1=83=20?= =?UTF-8?q?=D0=B2=20`CatsViewModel.kt`=20=D1=81=20=D0=BA=D0=BE=D0=BB=D0=B1?= =?UTF-8?q?=D0=B5=D0=BA=D0=BE=D0=B2=20=D0=BD=D0=B0=20RX.=20=D0=9B=D0=BE?= =?UTF-8?q?=D0=B3=D0=B8=D0=BA=D1=83=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D1=83=D1=81=D0=BF=D0=B5=D1=85=D0=B0/?= =?UTF-8?q?=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=B8=D0=B7=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BB=D0=BB=D0=B1=D0=B5=D0=BA=D0=B0=20=D0=BD=D0=B5=D0=BE?= =?UTF-8?q?=D0=B1=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=D0=BE=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D1=81=D1=82=D0=B8=20=D0=B2=20=D1=82=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=BB=D0=B1=D0=B5=D0=BA=D0=B8=20RX=20=D1=86?= =?UTF-8?q?=D0=B5=D0=BF=D0=BE=D1=87=D0=BA=D0=B8.=20=D0=9D=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B1=D1=83=D0=B4=D1=8C=D1=82=D0=B5=20=D0=BE=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D0=B8=D1=82=D1=8C=20=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=BA=D0=B8=20=D0=BA=D0=BE=D0=B3=D0=B4=D0=B0=20`ViewMode?= =?UTF-8?q?l`=20=D1=83=D0=BD=D0=B8=D1=87=D1=82=D0=BE=D0=B6=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=D1=81=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/otus/homework/reactivecats/CatsViewModel.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt index e3449aad..344691b2 100644 --- a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt +++ b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt @@ -35,6 +35,11 @@ class CatsViewModel( } fun getFacts() {} + + override fun onCleared() { + super.onCleared() + compositeDisposable.clear() + } } class CatsViewModelFactory( From 00354ae25bf8a92c672be72b72615929128a3ce7 Mon Sep 17 00:00:00 2001 From: Beknur Patsaev Date: Tue, 4 Feb 2025 00:27:12 +0300 Subject: [PATCH 3/5] =?UTF-8?q?3.=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7?= =?UTF-8?q?=D1=83=D0=B9=D1=82=D0=B5=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20`otus.homework.reactivecats.LocalCatFactsGenerator#gen?= =?UTF-8?q?erateCatFact`,=20=D1=82=D0=B0=D0=BA,=20=D1=87=D1=82=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=20=D0=BE=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80?= =?UTF-8?q?=D0=B0=D1=89=D0=B0=D0=BB=D0=B0=20`Fact`=20=D1=81=D0=BE=20=D1=81?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B0=D0=B9=D0=BD=D0=BE=D0=B9=20=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BA=D0=BE=D0=B9=20=D0=B8=D0=B7=20=D0=BC=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D0=B8=D0=B2=D0=B0=20=D1=81=D1=82=D1=80=D0=BE=D0=BA?= =?UTF-8?q?=20`R.array.local=5Fcat=5Ffacts`=20=D0=BE=D0=B1=D0=B5=D1=80?= =?UTF-8?q?=D0=BD=D1=83=D1=82=D1=83=D1=8E=20=D0=B2=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=D1=8F=D1=89=D0=B8=D0=B9=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B8=D0=BC(`Flowable`/`Single`/`Observable`=20=D0=B8=20=D1=82?= =?UTF-8?q?.=D0=BF)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 4. Реализуйте функцию `otus.homework.reactivecats.LocalCatFactsGenerator#generateCatFactPeriodically` так, чтобы она эмитила `Fact` со случайной строкой из массива строк `R.array.local_cat_facts` каждые 2000 миллисекунд. Если вновь заэмиченный Fact совпадает с предыдущим - пропускаем элемент. --- .../homework/reactivecats/LocalCatFactsGenerator.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt b/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt index 4481062e..f1849edd 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,11 @@ class LocalCatFactsGenerator( * обернутую в подходящий стрим(Flowable/Single/Observable и т.п) */ fun generateCatFact(): Single { - return Single.never() + println("XXX generateCatFact") + val strings = context.resources.getStringArray(R.array.local_cat_facts) + val randomId = Random.nextInt(strings.size) + val fact = Fact(strings[randomId]) + return Single.just(fact) } /** @@ -24,7 +29,9 @@ 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(2000, TimeUnit.MILLISECONDS) + .map { + Fact(context.resources.getStringArray(R.array.local_cat_facts)[Random.nextInt(5)]) + }.distinctUntilChanged() } } \ No newline at end of file From 82231e68585b2dd84fb7a9a8fdb908f2a7d89dd4 Mon Sep 17 00:00:00 2001 From: Beknur Patsaev Date: Tue, 4 Feb 2025 19:42:52 +0300 Subject: [PATCH 4/5] =?UTF-8?q?5.=20=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7?= =?UTF-8?q?=D1=83=D0=B9=D1=82=D0=B5=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20`otus.homework.reactivecats.CatsViewModel#getFacts`=20?= =?UTF-8?q?=D1=81=D0=BB=D0=B5=D0=B4=D1=83=D1=8E=D1=89=D0=B8=D0=BC=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=BC:=20=D0=BA=D0=B0=D0=B6?= =?UTF-8?q?=D0=B4=D1=8B=D0=B5=202=20=D1=81=D0=B5=D0=BA=D1=83=D0=BD=D0=B4?= =?UTF-8?q?=D1=8B=20=D0=B8=D0=B4=D0=B5=D0=BC=20=D0=B2=20=D1=81=D0=B5=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B7=D0=B0=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=BC=20=D1=84?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=BE=D0=BC,=20=D0=B5=D1=81=D0=BB=D0=B8=20?= =?UTF-8?q?=D1=81=D0=B5=D1=82=D0=B5=D0=B2=D0=BE=D0=B9=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81=20=D0=B7=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D0=B8?= =?UTF-8?q?=D0=BB=D1=81=D1=8F=20=D0=BD=D0=B5=D1=83=D1=81=D0=BF=D0=B5=D1=88?= =?UTF-8?q?=D0=BD=D0=BE,=20=D1=82=D0=BE=20=D0=B2=20=D0=BA=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B2=D0=B5=20=D1=84=D0=BE=D0=BB=D0=BB=D0=B1?= =?UTF-8?q?=D0=B5=D0=BA=D0=B0=20=D0=B8=D0=B4=D0=B5=D0=BC=20=D0=B7=D0=B0=20?= =?UTF-8?q?=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D0=BC=20=D0=B2=20=D1=83=D0=B6?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20`otus.homework.reactivecats.LocalCat?= =?UTF-8?q?FactsGenerator#generateCatFact`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../homework/reactivecats/CatsViewModel.kt | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt index 344691b2..ad6e5a8d 100644 --- a/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt +++ b/app/src/main/java/otus/homework/reactivecats/CatsViewModel.kt @@ -5,9 +5,11 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import io.reactivex.schedulers.Schedulers +import java.util.concurrent.TimeUnit class CatsViewModel( catsService: CatsService, @@ -21,16 +23,28 @@ class CatsViewModel( init { compositeDisposable.addAll( - catsService.getCatFact() + Observable.interval(2000, TimeUnit.MILLISECONDS) + .concatMap { catsService.getCatFact().toObservable() } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ fact -> - _catsLiveData.value = Success(fact) - }, { - _catsLiveData.value = Error( - it?.message.toString() - ) - }) + .subscribe( + { fact -> + _catsLiveData.value = Success(fact) + }, + { + compositeDisposable.add( + localCatFactsGenerator.generateCatFact() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { localFact -> + _catsLiveData.value = Success(localFact) + }, + { } + ) + ) + } + ) ) } From 8739681f237d21a843946a0160934336b88d4000 Mon Sep 17 00:00:00 2001 From: Beknur Patsaev Date: Tue, 4 Feb 2025 20:07:31 +0300 Subject: [PATCH 5/5] remove prints --- .../java/otus/homework/reactivecats/LocalCatFactsGenerator.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt b/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt index f1849edd..b101cc26 100644 --- a/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt +++ b/app/src/main/java/otus/homework/reactivecats/LocalCatFactsGenerator.kt @@ -16,7 +16,6 @@ class LocalCatFactsGenerator( * обернутую в подходящий стрим(Flowable/Single/Observable и т.п) */ fun generateCatFact(): Single { - println("XXX generateCatFact") val strings = context.resources.getStringArray(R.array.local_cat_facts) val randomId = Random.nextInt(strings.size) val fact = Fact(strings[randomId])