From 564483548b16290fa037e78868d9137dbe5967ca Mon Sep 17 00:00:00 2001 From: Sergey Olshanov Date: Mon, 9 Oct 2023 00:55:55 +0500 Subject: [PATCH 1/2] home work has been done --- app/build.gradle | 18 +++-- .../java/otus/homework/coroutines/CatImage.kt | 8 +++ .../otus/homework/coroutines/CatViewModel.kt | 67 +++++++++++++++++++ .../otus/homework/coroutines/CatsMapper.kt | 9 +++ .../otus/homework/coroutines/CatsPresenter.kt | 43 +++++++++--- .../otus/homework/coroutines/CatsService.kt | 4 +- .../java/otus/homework/coroutines/CatsView.kt | 17 +++-- .../otus/homework/coroutines/CrashMonitor.kt | 6 +- .../otus/homework/coroutines/DiContainer.kt | 8 +++ .../java/otus/homework/coroutines/Fact.kt | 41 +++++++----- .../homework/coroutines/FactAndImageModel.kt | 6 ++ .../homework/coroutines/ImageCatsService.kt | 10 +++ .../otus/homework/coroutines/MainActivity.kt | 38 ++++++++--- .../otus/homework/coroutines/MainFactory.kt | 17 +++++ .../java/otus/homework/coroutines/Result.kt | 5 ++ build.gradle | 2 +- 16 files changed, 244 insertions(+), 55 deletions(-) create mode 100644 app/src/main/java/otus/homework/coroutines/CatImage.kt create mode 100644 app/src/main/java/otus/homework/coroutines/CatViewModel.kt create mode 100644 app/src/main/java/otus/homework/coroutines/CatsMapper.kt create mode 100644 app/src/main/java/otus/homework/coroutines/FactAndImageModel.kt create mode 100644 app/src/main/java/otus/homework/coroutines/ImageCatsService.kt create mode 100644 app/src/main/java/otus/homework/coroutines/MainFactory.kt create mode 100644 app/src/main/java/otus/homework/coroutines/Result.kt diff --git a/app/build.gradle b/app/build.gradle index 679dbba4..53895a1a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,13 +4,13 @@ plugins { } android { - compileSdkVersion 30 + compileSdkVersion 34 buildToolsVersion "30.0.3" defaultConfig { applicationId "otus.homework.coroutines" minSdkVersion 23 - targetSdkVersion 30 + targetSdkVersion 34 versionCode 1 versionName "1.0" @@ -34,12 +34,16 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.3.2' + implementation 'androidx.core:core-ktx:1.12.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.8.6' - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'com.google.android.material:material:1.3.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.10.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.squareup.picasso:picasso:2.71828' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' } \ No newline at end of file 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..b6cd1ef9 --- /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("image") + val image: String, +) diff --git a/app/src/main/java/otus/homework/coroutines/CatViewModel.kt b/app/src/main/java/otus/homework/coroutines/CatViewModel.kt new file mode 100644 index 00000000..d61f49c5 --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/CatViewModel.kt @@ -0,0 +1,67 @@ +package otus.homework.coroutines + +import android.app.Application +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.* + +class CatViewModel( + private val catsService: CatsService, + private val imageCatsService: ImageCatsService, + private val application: Application, + private val catsMapper: CatsMapper +): ViewModel() { + + companion object { + + private const val SOCKET_TIMEOUT_EXCEPTION = "Не удалось получить ответ от сервера" + private const val ERROR_MESSAGE = "Произошла ошибка" + } + + private var _catsView: ICatsView? = null + + private val errorHandler = CoroutineExceptionHandler { _, exception -> + CrashMonitor.trackWarning(application, exception.message ?: ERROR_MESSAGE) + } + + fun onInitComplete() { + viewModelScope.launch(errorHandler) { + when(val responseResult = onInitCompleteResponse()) { + is Success -> { + _catsView?.populate(responseResult.data) + } + is Error -> { + CrashMonitor.trackWarning(application, responseResult.message) + } + } + } + } + + private suspend fun onInitCompleteResponse(): Result { + return try { + val response = catsService.getCatFact() + val imageResponse = imageCatsService.getCatImage() + if ((response.isSuccessful && response.body() != null) && (imageResponse.isSuccessful && imageResponse.body() != null)) { + val factAndImage = catsMapper.toFactAndImage( + fact = response.body()?.fact, + image = imageResponse.body()?.image + ) + Success(factAndImage) + } else { + Error(SOCKET_TIMEOUT_EXCEPTION) + } + } catch (e: java.net.SocketTimeoutException) { + Error(SOCKET_TIMEOUT_EXCEPTION) + } catch (e: Exception) { + Error(e.message ?: ERROR_MESSAGE) + } + } + + fun attachView(catsView: ICatsView) { + _catsView = catsView + } + + fun detachView() { + _catsView = null + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/CatsMapper.kt b/app/src/main/java/otus/homework/coroutines/CatsMapper.kt new file mode 100644 index 00000000..a83e6e6f --- /dev/null +++ b/app/src/main/java/otus/homework/coroutines/CatsMapper.kt @@ -0,0 +1,9 @@ +package otus.homework.coroutines + +class CatsMapper { + + fun toFactAndImage(fact: String?, image: String?): FactAndImageModel = FactAndImageModel( + fact = fact.orEmpty(), + image = image.orEmpty() + ) +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt index e4b05120..16b7bf74 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsPresenter.kt @@ -1,28 +1,48 @@ package otus.homework.coroutines +import android.content.Context +import kotlinx.coroutines.* import retrofit2.Call import retrofit2.Callback import retrofit2.Response class CatsPresenter( - private val catsService: CatsService + private val catsService: CatsService, + private val imageCatsService: ImageCatsService, + private val context: Context, + private val catMapper: CatsMapper ) { + companion object { + + private const val CATS_COROUTINES = "CatsCoroutine" + private const val SOCKET_TIMEOUT_EXCEPTION = "Не удалось получить ответ от сервера" + private const val ERROR_MESSAGE = "Произошла ошибка" + } + private var _catsView: ICatsView? = null - fun onInitComplete() { - catsService.getCatFact().enqueue(object : Callback { + private val presenterScope = CoroutineScope(Dispatchers.Main + CoroutineName(CATS_COROUTINES)) - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful && response.body() != null) { - _catsView?.populate(response.body()!!) + fun onInitComplete() { + presenterScope.launch { + try { + val response = catsService.getCatFact() + val imageResponse = imageCatsService.getCatImage() + if ((response.isSuccessful && response.body() != null) && (imageResponse.isSuccessful && + imageResponse.body() != null)) { + val factAndImage = catMapper.toFactAndImage( + fact = response.body()?.fact, + image = imageResponse.body()?.image + ) + _catsView?.populate(factAndImage) } + } catch (e: java.net.SocketTimeoutException) { + CrashMonitor.trackWarning(context, SOCKET_TIMEOUT_EXCEPTION) + } catch (e: Exception) { + CrashMonitor.trackWarning(context, e.message ?: ERROR_MESSAGE) } - - override fun onFailure(call: Call, t: Throwable) { - CrashMonitor.trackWarning() - } - }) + } } fun attachView(catsView: ICatsView) { @@ -31,5 +51,6 @@ class CatsPresenter( fun detachView() { _catsView = null + presenterScope.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..be937729 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsService.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsService.kt @@ -1,10 +1,10 @@ package otus.homework.coroutines -import retrofit2.Call +import retrofit2.Response import retrofit2.http.GET interface CatsService { @GET("fact") - fun getCatFact() : Call + suspend fun getCatFact() : Response } \ 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 30ac2531..cc014247 100644 --- a/app/src/main/java/otus/homework/coroutines/CatsView.kt +++ b/app/src/main/java/otus/homework/coroutines/CatsView.kt @@ -2,9 +2,9 @@ package otus.homework.coroutines import android.content.Context import android.util.AttributeSet -import android.widget.Button -import android.widget.TextView +import android.widget.* import androidx.constraintlayout.widget.ConstraintLayout +import com.squareup.picasso.Picasso class CatsView @JvmOverloads constructor( context: Context, @@ -12,21 +12,24 @@ class CatsView @JvmOverloads constructor( defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView { - var presenter :CatsPresenter? = null + // var presenter: CatsPresenter? = null + var viewModel: CatViewModel? = null override fun onFinishInflate() { super.onFinishInflate() findViewById