From 2cfbd09bc7c53e28eda330e68049ed4b8231a295 Mon Sep 17 00:00:00 2001 From: Bogdan Patseev Date: Sun, 25 May 2025 21:42:49 +0300 Subject: [PATCH 1/3] task 1 --- .../otus/homework/coroutines/CatsPresenter.kt | 31 +++++++++++-------- .../otus/homework/coroutines/CatsService.kt | 2 +- .../java/otus/homework/coroutines/CatsView.kt | 7 +++++ 3 files changed, 26 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..10a1f4e2 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt @@ -1,28 +1,28 @@ package otus.homework.coroutines -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response +import kotlinx.coroutines.* +import java.net.SocketTimeoutException class CatsPresenter( private val catsService: CatsService ) { private var _catsView: ICatsView? = null + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate + 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 { + _catsView?.populate(catsService.getCatFact()) + } catch (e: Exception) { + if (e is SocketTimeoutException) { + _catsView?.showToast(TIME_OUT) + } else { + CrashMonitor.trackWarning() + _catsView?.showToast(e.message ?: e.toString()) } } - - override fun onFailure(call: Call, t: Throwable) { - CrashMonitor.trackWarning() - } - }) + } } fun attachView(catsView: ICatsView) { @@ -31,5 +31,10 @@ class CatsPresenter( fun detachView() { _catsView = null + scope.cancel() + } + + companion object { + const val TIME_OUT = "Не удалось получить ответ от сервера" } } \ 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..436a1e6e 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,15 @@ class CatsView @JvmOverloads constructor( override fun populate(fact: Fact) { findViewById(R.id.fact_textView).text = fact.fact } + + override fun showToast(message: String) { + Toast.makeText(context, message, Toast.LENGTH_SHORT).show() + } } interface ICatsView { fun populate(fact: Fact) + + fun showToast(message: String) } \ No newline at end of file From 24eb2e62f81296cee214fc0abe39e9ebd46e3061 Mon Sep 17 00:00:00 2001 From: Bogdan Patseev Date: Sun, 25 May 2025 22:29:58 +0300 Subject: [PATCH 2/3] task 2 --- .../otus/homework/coroutines/CatsPresenter.kt | 18 +++++- .../otus/homework/coroutines/CatsService.kt | 3 +- .../java/otus/homework/coroutines/CatsView.kt | 13 +++-- .../otus/homework/coroutines/DiContainer.kt | 9 +++ .../java/otus/homework/coroutines/Fact.kt | 8 +-- .../otus/homework/coroutines/FactWithPhoto.kt | 6 ++ .../otus/homework/coroutines/MainActivity.kt | 4 +- .../java/otus/homework/coroutines/Photo.kt | 14 +++++ .../otus/homework/coroutines/PhotoService.kt | 9 +++ app/src/main/res/layout/activity_main.xml | 55 +++++++++++-------- .../homework/coroutines/ExampleUnitTest.kt | 3 +- 11 files changed, 104 insertions(+), 38 deletions(-) create mode 100644 app/src/main/java/otus/homework/coroutines/FactWithPhoto.kt create mode 100644 app/src/main/java/otus/homework/coroutines/Photo.kt create mode 100644 app/src/main/java/otus/homework/coroutines/PhotoService.kt diff --git a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt index 10a1f4e2..e592f8cf 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt @@ -4,7 +4,8 @@ import kotlinx.coroutines.* import java.net.SocketTimeoutException class CatsPresenter( - private val catsService: CatsService + private val catsService: CatsService, + private val photoService: PhotoService, ) { private var _catsView: ICatsView? = null @@ -13,7 +14,19 @@ class CatsPresenter( fun onInitComplete() { scope.launch { try { - _catsView?.populate(catsService.getCatFact()) + coroutineScope { + val fact = async(Dispatchers.IO) { + catsService.getCatFact() + } + val photo = async(Dispatchers.IO) { + photoService.getPhoto() + } + val factWithPhoto = FactWithPhoto( + fact = fact.await(), + photo = photo.await().first().url + ) + _catsView?.populate(factWithPhoto) + } } catch (e: Exception) { if (e is SocketTimeoutException) { _catsView?.showToast(TIME_OUT) @@ -25,6 +38,7 @@ class CatsPresenter( } } + fun attachView(catsView: ICatsView) { _catsView = catsView } diff --git a/app/src/main/java/otus/homework/coroutines/CatsService.kt b/app/src/main/java/otus/homework/coroutines/CatsService.kt index ca9e3f73..829b930c 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsService.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsService.kt @@ -1,10 +1,9 @@ package otus.homework.coroutines -import retrofit2.Call import retrofit2.http.GET interface CatsService { @GET("fact") - suspend fun getCatFact() : Fact + 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 436a1e6e..edefe0d6 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, @@ -13,7 +15,7 @@ class CatsView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView { - var presenter :CatsPresenter? = null + var presenter: CatsPresenter? = null override fun onFinishInflate() { super.onFinishInflate() @@ -22,8 +24,11 @@ class CatsView @JvmOverloads constructor( } } - override fun populate(fact: Fact) { - findViewById(R.id.fact_textView).text = fact.fact + override fun populate(factWithPhoto: FactWithPhoto) { + findViewById(R.id.fact_textView).text = factWithPhoto.fact.fact + Picasso.get() + .load(factWithPhoto.photo) + .into(findViewById(R.id.image)) } override fun showToast(message: String) { @@ -33,7 +38,7 @@ class CatsView @JvmOverloads constructor( interface ICatsView { - fun populate(fact: Fact) + fun populate(factWithPhoto: FactWithPhoto) fun showToast(message: String) } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/DiContainer.kt b/app/src/main/java/otus/homework/coroutines/DiContainer.kt index 23ddc3b2..309cccca 100644 --- a/app/src/main/java/otus/homework/coroutines/DiContainer.kt +++ b/app/src/main/java/otus/homework/coroutines/DiContainer.kt @@ -12,5 +12,14 @@ class DiContainer { .build() } + private val retrofitPhoto by lazy { + Retrofit.Builder() + .baseUrl("https://api.thecatapi.com/v1/images/") + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + val service by lazy { retrofit.create(CatsService::class.java) } + + val photoService by lazy { retrofitPhoto.create(PhotoService::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..a47accb1 100644 --- a/app/src/main/java/otus/homework/coroutines/Fact.kt +++ b/app/src/main/java/otus/homework/coroutines/Fact.kt @@ -3,8 +3,8 @@ package otus.homework.coroutines import com.google.gson.annotations.SerializedName data class Fact( - @field:SerializedName("fact") - val fact: String, - @field:SerializedName("length") - val length: Int + @field:SerializedName("fact") + val fact: String, + @field:SerializedName("length") + val length: Int ) \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/FactWithPhoto.kt b/app/src/main/java/otus/homework/coroutines/FactWithPhoto.kt new file mode 100644 index 00000000..ac0fe667 --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/FactWithPhoto.kt @@ -0,0 +1,6 @@ +package otus.homework.coroutines + +data class FactWithPhoto( + val fact: Fact, + val photo: String +) diff --git a/app/src/main/java/otus/homework/coroutines/MainActivity.kt b/app/src/main/java/otus/homework/coroutines/MainActivity.kt index a9dafb3b..5e8bd914 100644 --- a/app/src/main/java/otus/homework/coroutines/MainActivity.kt +++ b/app/src/main/java/otus/homework/coroutines/MainActivity.kt @@ -1,7 +1,7 @@ package otus.homework.coroutines -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { @@ -15,7 +15,7 @@ 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.photoService) view.presenter = catsPresenter catsPresenter.attachView(view) catsPresenter.onInitComplete() diff --git a/app/src/main/java/otus/homework/coroutines/Photo.kt b/app/src/main/java/otus/homework/coroutines/Photo.kt new file mode 100644 index 00000000..7af19587 --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/Photo.kt @@ -0,0 +1,14 @@ +package otus.homework.coroutines + +import com.google.gson.annotations.SerializedName + +data class Photo( + @field:SerializedName("id") + val id: String, + @field:SerializedName("url") + val url: String, + @field:SerializedName("width") + val width: Int, + @field:SerializedName("height") + val height: Int, +) diff --git a/app/src/main/java/otus/homework/coroutines/PhotoService.kt b/app/src/main/java/otus/homework/coroutines/PhotoService.kt new file mode 100644 index 00000000..8f26574d --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/PhotoService.kt @@ -0,0 +1,9 @@ +package otus.homework.coroutines + +import retrofit2.http.GET + +interface PhotoService { + + @GET("search") + suspend fun getPhoto(): List +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9508066d..733b6d28 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,30 +1,41 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:padding="16dp" + android:layout_height="match_parent" + tools:context=".MainActivity"> + + android:id="@+id/fact_textView" + android:textColor="@color/black" + android:textSize="24sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_constraintBottom_toTopOf="@+id/button" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/image"/>