Skip to content

Выполнено ДЗ Coroutines Homework #238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ dependencies {
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.squareup.picasso:picasso:2.71828'
runtimeOnly 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7'
}
6 changes: 6 additions & 0 deletions app/src/main/java/otus/homework/coroutines/CatModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package otus.homework.coroutines

data class CatModel(
val fact: String,
val photoUrl: String,
)
52 changes: 52 additions & 0 deletions app/src/main/java/otus/homework/coroutines/CatViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package otus.homework.coroutines

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch
import java.net.SocketTimeoutException

class CatViewModel(
private val catsFactService: CatsFactService,
private val catsImageService: CatsImageService,
) : ViewModel() {

private var _catsView: ICatsView? = null

private val _liveData = MutableLiveData<Result>()
val liveData = _liveData

private val exceptionHandler = CoroutineExceptionHandler { _, _ ->
CrashMonitor.trackWarning()
}

fun onInitComplete() {
viewModelScope.launch(exceptionHandler) {
try {
_liveData.postValue(
Result.Success(
CatModel(
catsFactService.getCatFact().fact,
catsImageService.getCatImage().first().url
)
)
)
} catch (e: SocketTimeoutException) {
_liveData.postValue(Result.Error("Не удалось получить ответ от сервером"))
} catch (e: Throwable) {
_liveData.postValue(Result.Error(e.message))
throw e
}

}
}

fun attachView(catsView: ICatsView) {
_catsView = catsView
}

fun detachView() {
_catsView = null
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package otus.homework.coroutines

import retrofit2.Call
import retrofit2.http.GET

interface CatsService {
interface CatsFactService {

@GET("fact")
fun getCatFact() : Call<Fact>
suspend fun getCatFact() : Fact
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package otus.homework.coroutines

import retrofit2.http.GET

interface CatsImageService {

@GET("/v1/images/search")
suspend fun getCatImage() : List<Image>
}
35 changes: 0 additions & 35 deletions app/src/main/java/otus/homework/coroutines/CatsPresenter.kt

This file was deleted.

24 changes: 18 additions & 6 deletions app/src/main/java/otus/homework/coroutines/CatsView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ 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,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
defStyleAttr: Int = 0,
) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView {

var presenter :CatsPresenter? = null
var presenter: CatViewModel? = null
var viewModel: CatViewModel? = null

override fun onFinishInflate() {
super.onFinishInflate()
Expand All @@ -21,12 +25,20 @@ class CatsView @JvmOverloads constructor(
}
}

override fun populate(fact: Fact) {
findViewById<TextView>(R.id.fact_textView).text = fact.fact
override fun populate(catModel: CatModel) {
findViewById<TextView>(R.id.fact_textView).text = catModel.fact
Picasso.get()
.load(catModel.photoUrl)
.into(findViewById<ImageView>(R.id.imageView))
}

override fun toast(message: String?) {
Toast.makeText(context, message ?: "unknown error", Toast.LENGTH_LONG).show()
}
}

interface ICatsView {

fun populate(fact: Fact)
}
fun populate(catModel: CatModel)
fun toast(message: String?)
}
1 change: 1 addition & 0 deletions app/src/main/java/otus/homework/coroutines/CrashMonitor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ object CrashMonitor {
* Pretend this is Crashlytics/AppCenter
*/
fun trackWarning() {
println("Warning tracked!")
}
}
15 changes: 12 additions & 3 deletions app/src/main/java/otus/homework/coroutines/DiContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ import retrofit2.converter.gson.GsonConverterFactory

class DiContainer {

private val retrofit by lazy {
private val catsFactClient by lazy {
Retrofit.Builder()
.baseUrl("https://catfact.ninja/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}

val service by lazy { retrofit.create(CatsService::class.java) }
}
private val catsImageClient by lazy {
Retrofit.Builder()
.baseUrl("https://api.thecatapi.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
}

val catsFactService: CatsFactService by lazy { catsFactClient.create(CatsFactService::class.java) }

val catsImageService: CatsImageService by lazy { catsImageClient.create(CatsImageService::class.java) }
}
8 changes: 8 additions & 0 deletions app/src/main/java/otus/homework/coroutines/Image.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package otus.homework.coroutines

import com.google.gson.annotations.SerializedName

data class Image(
@field:SerializedName("url")
val url: String,
)
38 changes: 32 additions & 6 deletions app/src/main/java/otus/homework/coroutines/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package otus.homework.coroutines

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider

class MainActivity : AppCompatActivity() {

lateinit var catsPresenter: CatsPresenter
private lateinit var catsViewModel: CatViewModel

private val diContainer = DiContainer()

Expand All @@ -15,16 +17,40 @@ class MainActivity : AppCompatActivity() {
val view = layoutInflater.inflate(R.layout.activity_main, null) as CatsView
setContentView(view)

catsPresenter = CatsPresenter(diContainer.service)
catsViewModel =
ViewModelProvider(this, ViewModelFactory(diContainer)).get(CatViewModel::class.java)

/*catsPresenter = CatViewModel(diContainer.catsFactService, diContainer.catsImageService)
view.presenter = catsPresenter
catsPresenter.attachView(view)
catsPresenter.onInitComplete()
catsPresenter.onInitComplete()*/

view.presenter = catsViewModel
catsViewModel.attachView(view)
catsViewModel.onInitComplete()

catsViewModel.liveData.observe(this) {
when (it) {
is Result.Success -> view.populate(it.catModel)
is Result.Error -> view.toast(it.message)
}
}
}

override fun onStop() {
if (isFinishing) {
catsPresenter.detachView()
//catsPresenter.detachView()
catsViewModel.detachView()
}
super.onStop()
}
}

class ViewModelFactory(private val diContainer: DiContainer) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(CatViewModel::class.java)) {
return CatViewModel(diContainer.catsFactService, diContainer.catsImageService) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
}
8 changes: 8 additions & 0 deletions app/src/main/java/otus/homework/coroutines/Result.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package otus.homework.coroutines


sealed class Result {

data class Success(val catModel: CatModel) : Result()
data class Error(val message: String?) : Result()
}
15 changes: 12 additions & 3 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
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"
android:padding="16dp"
tools:context=".MainActivity">

<TextView
android:id="@+id/fact_textView"
android:textColor="@color/black"
android:textSize="24sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
Expand All @@ -27,4 +27,13 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fact_textView" />

<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription=""
app:layout_constraintBottom_toTopOf="@+id/fact_textView"
tools:layout_editor_absoluteX="16dp"
tools:srcCompat="@tools:sample/avatars" />

</otus.homework.coroutines.CatsView>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<resources>
<string name="app_name">Cat Facts </string>
<string name="more_facts">More Facts</string>

<string name="fetch_error">Не удалось получить ответ от сервером</string>
</resources>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.1'
classpath 'com.android.tools.build:gradle:8.6.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

// NOTE: Do not place your application dependencies here; they belong
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon Jan 15 23:17:01 GST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists