From c7b857ffb2c0138bfb4c4d7940ad8b4af9e92600 Mon Sep 17 00:00:00 2001 From: dmilkov97 Date: Sun, 19 Oct 2025 15:11:40 +0700 Subject: [PATCH 1/7] 1st task complete --- .../otus/homework/coroutines/CatsPresenter.kt | 37 ++++++++++++------- .../otus/homework/coroutines/CatsService.kt | 2 +- .../java/otus/homework/coroutines/CatsView.kt | 12 ++++++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt index e4b05120..a828e4bf 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt @@ -1,28 +1,38 @@ package otus.homework.coroutines -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.launch +import java.net.SocketTimeoutException class CatsPresenter( private val catsService: CatsService ) { private var _catsView: ICatsView? = null + val job = SupervisorJob() + private val scope = CoroutineScope(Dispatchers.Main + job + CoroutineName("CatsCoroutine")) fun onInitComplete() { - catsService.getCatFact().enqueue(object : Callback { - - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful && response.body() != null) { - _catsView?.populate(response.body()!!) - } + scope.launch { + try { + val fact = catsService.getCatFact() + _catsView?.populate(fact) } - - override fun onFailure(call: Call, t: Throwable) { - CrashMonitor.trackWarning() + catch (e: Exception) { + when (e) { + is SocketTimeoutException -> { + _catsView?.showServerErrorToast() + } + else -> { + _catsView?.showToast(e.message.toString()) + CrashMonitor.trackWarning() + } + } } - }) + } } fun attachView(catsView: ICatsView) { @@ -31,5 +41,6 @@ class CatsPresenter( fun detachView() { _catsView = null + job.cancel() } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/CatsService.kt b/app/src/main/java/otus/homework/coroutines/CatsService.kt index 479b2cfb..ca9e3f73 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsService.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsService.kt @@ -6,5 +6,5 @@ import retrofit2.http.GET interface CatsService { @GET("fact") - fun getCatFact() : Call + suspend fun getCatFact() : Fact } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/CatsView.kt b/app/src/main/java/otus/homework/coroutines/CatsView.kt index be04b2a8..ee8c643a 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsView.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsView.kt @@ -4,6 +4,7 @@ import android.content.Context import android.util.AttributeSet import android.widget.Button import android.widget.TextView +import android.widget.Toast import androidx.constraintlayout.widget.ConstraintLayout class CatsView @JvmOverloads constructor( @@ -24,9 +25,20 @@ class CatsView @JvmOverloads constructor( override fun populate(fact: Fact) { findViewById(R.id.fact_textView).text = fact.fact } + + override fun showServerErrorToast() { + Toast.makeText(context, "Не удалось получить ответ от сервером", Toast.LENGTH_LONG).show() + } + + override fun showToast(message: String) { + Toast.makeText(context, message, Toast.LENGTH_LONG).show() + + } } interface ICatsView { fun populate(fact: Fact) + fun showServerErrorToast() + fun showToast(message: String) } \ No newline at end of file From b64b88d3e67b1060079b64afc4d20f18d7c97c96 Mon Sep 17 00:00:00 2001 From: dmilkov97 Date: Sun, 19 Oct 2025 17:45:23 +0700 Subject: [PATCH 2/7] 2nd task complete --- .../java/otus/homework/coroutines/CatImage.kt | 3 +++ .../otus/homework/coroutines/CatsPresenter.kt | 13 ++++++++++--- .../otus/homework/coroutines/CatsService.kt | 6 +++++- .../java/otus/homework/coroutines/CatsView.kt | 8 ++++++++ .../otus/homework/coroutines/DiContainer.kt | 7 +++++++ .../main/java/otus/homework/coroutines/Fact.kt | 4 +++- .../otus/homework/coroutines/MainActivity.kt | 4 +++- app/src/main/res/layout/activity_main.xml | 17 +++++++++++++---- 8 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/otus/homework/coroutines/CatImage.kt diff --git a/app/src/main/java/otus/homework/coroutines/CatImage.kt b/app/src/main/java/otus/homework/coroutines/CatImage.kt new file mode 100644 index 00000000..0679ca84 --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/CatImage.kt @@ -0,0 +1,3 @@ +package otus.homework.coroutines + +data class CatImage(val url: String) diff --git a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt index a828e4bf..b6d49141 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt @@ -4,13 +4,14 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.async import kotlinx.coroutines.launch import java.net.SocketTimeoutException class CatsPresenter( - private val catsService: CatsService + private val catsService: CatsService, + private val catsServicePics: CatsServicePics ) { - private var _catsView: ICatsView? = null val job = SupervisorJob() private val scope = CoroutineScope(Dispatchers.Main + job + CoroutineName("CatsCoroutine")) @@ -18,7 +19,13 @@ class CatsPresenter( fun onInitComplete() { scope.launch { try { - val fact = catsService.getCatFact() + val factDeferred = async { catsService.getCatFact() } + val imageDeferred = async { catsServicePics.getCatPicUrl() } + + val fact = factDeferred.await() + val pic = imageDeferred.await() + val url = pic.firstOrNull()?.url + fact.url = url.toString() _catsView?.populate(fact) } catch (e: Exception) { diff --git a/app/src/main/java/otus/homework/coroutines/CatsService.kt b/app/src/main/java/otus/homework/coroutines/CatsService.kt index ca9e3f73..c0a5dbcb 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsService.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsService.kt @@ -1,10 +1,14 @@ package otus.homework.coroutines -import retrofit2.Call import retrofit2.http.GET interface CatsService { @GET("fact") suspend fun getCatFact() : Fact + +} +interface CatsServicePics { + @GET("v1/images/search") + suspend fun getCatPicUrl() : List } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/CatsView.kt b/app/src/main/java/otus/homework/coroutines/CatsView.kt index ee8c643a..6962311b 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsView.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsView.kt @@ -3,9 +3,11 @@ package otus.homework.coroutines import android.content.Context import android.util.AttributeSet import android.widget.Button +import android.widget.ImageView import android.widget.TextView import android.widget.Toast import androidx.constraintlayout.widget.ConstraintLayout +import com.squareup.picasso.Picasso class CatsView @JvmOverloads constructor( context: Context, @@ -21,9 +23,15 @@ class CatsView @JvmOverloads constructor( presenter?.onInitComplete() } } + fun loadImageFromUrl(url: String, imageView: ImageView) { + Picasso.get() + .load(url) + .into(imageView) + } override fun populate(fact: Fact) { findViewById(R.id.fact_textView).text = fact.fact + loadImageFromUrl(fact.url, findViewById(R.id.cat_imgView)) } override fun showServerErrorToast() { diff --git a/app/src/main/java/otus/homework/coroutines/DiContainer.kt b/app/src/main/java/otus/homework/coroutines/DiContainer.kt index 23ddc3b2..1d150585 100644 --- a/app/src/main/java/otus/homework/coroutines/DiContainer.kt +++ b/app/src/main/java/otus/homework/coroutines/DiContainer.kt @@ -11,6 +11,13 @@ class DiContainer { .addConverterFactory(GsonConverterFactory.create()) .build() } + private val retrofitCatsPics by lazy { + Retrofit.Builder() + .baseUrl("https://api.thecatapi.com/") + .addConverterFactory(GsonConverterFactory.create()) + .build() + } val service by lazy { retrofit.create(CatsService::class.java) } + val serviceCatsPics by lazy { retrofitCatsPics.create(CatsServicePics::class.java) } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/Fact.kt b/app/src/main/java/otus/homework/coroutines/Fact.kt index 643a5a33..a1aaf3a3 100644 --- a/app/src/main/java/otus/homework/coroutines/Fact.kt +++ b/app/src/main/java/otus/homework/coroutines/Fact.kt @@ -6,5 +6,7 @@ data class Fact( @field:SerializedName("fact") val fact: String, @field:SerializedName("length") - val length: Int + val length: Int, + @field:SerializedName("url") + var url: String ) \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/MainActivity.kt b/app/src/main/java/otus/homework/coroutines/MainActivity.kt index a9dafb3b..77c464e6 100644 --- a/app/src/main/java/otus/homework/coroutines/MainActivity.kt +++ b/app/src/main/java/otus/homework/coroutines/MainActivity.kt @@ -15,7 +15,9 @@ class MainActivity : AppCompatActivity() { val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView setContentView(view) - catsPresenter = CatsPresenter(diContainer.service) + catsPresenter = CatsPresenter( + diContainer.service, + diContainer.serviceCatsPics) view.presenter = catsPresenter catsPresenter.attachView(view) catsPresenter.onInitComplete() diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9508066d..b474c1e8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,24 +7,33 @@ android:layout_height="match_parent" tools:context=".MainActivity"> + + app:layout_constraintTop_toBottomOf="@+id/cat_imgView" />