diff --git a/app/build.gradle b/app/build.gradle index a414e0e8..0a701443 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,6 +34,7 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.12.0' + implementation "androidx.activity:activity-ktx:1.8.0" implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.google.code.gson:gson:2.10' 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..bb7f6e6f --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/CatImage.kt @@ -0,0 +1,8 @@ +package otus.homework.coroutines + +import com.google.gson.annotations.SerializedName + +data class CatImage( + @field:SerializedName("file") + val file: String +) diff --git a/app/src/main/java/otus/homework/coroutines/CatImageService.kt b/app/src/main/java/otus/homework/coroutines/CatImageService.kt new file mode 100644 index 00000000..96d91810 --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/CatImageService.kt @@ -0,0 +1,8 @@ +package otus.homework.coroutines + +import retrofit2.http.GET + +interface CatImageService { + @GET("meow") + suspend fun getRandomCatImage(): CatImage +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/CatPresentationData.kt b/app/src/main/java/otus/homework/coroutines/CatPresentationData.kt new file mode 100644 index 00000000..7d62a20f --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/CatPresentationData.kt @@ -0,0 +1,6 @@ +package otus.homework.coroutines + +data class CatPresentationData( + val fact: String, + val imageUrl: String +) diff --git a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt index e4b05120..1ddfc259 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt @@ -1,28 +1,53 @@ package otus.homework.coroutines -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.async +import kotlinx.coroutines.launch +import java.net.SocketTimeoutException +import kotlin.coroutines.cancellation.CancellationException class CatsPresenter( - private val catsService: CatsService + private val catsService: CatsService, + private val catImageService: CatImageService ) { - private var _catsView: ICatsView? = null + private val presenterScope = PresenterScope() + private var currentJob: Job? = null fun onInitComplete() { - catsService.getCatFact().enqueue(object : Callback { + currentJob?.cancel() + currentJob = presenterScope.launch { + try { + val factDeferred = async(Dispatchers.IO) { catsService.getCatFact() } + val imageDeferred = async(Dispatchers.IO) { catImageService.getRandomCatImage() } - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful && response.body() != null) { - _catsView?.populate(response.body()!!) - } - } + val fact = factDeferred.await() + val image = imageDeferred.await() - override fun onFailure(call: Call, t: Throwable) { - CrashMonitor.trackWarning() + val presentationData = CatPresentationData( + fact = fact.fact, + imageUrl = image.file + ) + + _catsView?.populate(presentationData) + } catch (e: SocketTimeoutException) { + handleError("Не удалось получить ответ от сервером", e) + } catch (e: Exception) { + if (e is CancellationException) throw e + handleError(e.message ?: "Произошла ошибка", e) } - }) + } + } + + private fun handleError(message: String, exception: Exception) { + presenterScope.launch { + _catsView?.showError(message) + CrashMonitor.logException(exception) + } } fun attachView(catsView: ICatsView) { @@ -32,4 +57,23 @@ class CatsPresenter( fun detachView() { _catsView = null } + + fun onStop() { + currentJob?.cancel() + currentJob = null + } + + fun onDestroy() { + presenterScope.cancel() + } +} + +class PresenterScope : CoroutineScope { + private val job = SupervisorJob() + + override val coroutineContext = job + Dispatchers.Main + CoroutineName("CatsCoroutine") + + fun cancel() { + 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..db865d0c 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") - 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..64089ed2 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsView.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsView.kt @@ -2,9 +2,12 @@ package otus.homework.coroutines import android.content.Context import android.util.AttributeSet -import android.widget.Button +import android.widget.ImageView +import android.widget.ProgressBar import android.widget.TextView +import android.widget.Toast import androidx.constraintlayout.widget.ConstraintLayout +import com.squareup.picasso.Picasso class CatsView @JvmOverloads constructor( context: Context, @@ -12,21 +15,47 @@ class CatsView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView { - var presenter :CatsPresenter? = null + private lateinit var factTextView: TextView + private lateinit var catImageView: ImageView + private lateinit var progressBar: ProgressBar + private lateinit var button: android.widget.Button override fun onFinishInflate() { super.onFinishInflate() - findViewById