Skip to content

Coroutines-Homework #161

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 1 commit 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
10 changes: 8 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ plugins {
}

android {
compileSdkVersion 30
compileSdkVersion 33
buildToolsVersion "30.0.3"

defaultConfig {
applicationId "otus.homework.coroutines"
minSdkVersion 23
targetSdkVersion 30
targetSdkVersion 33
versionCode 1
versionName "1.0"

Expand All @@ -30,11 +30,17 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.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'
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Coroutines">
<activity android:name=".MainActivity"
<activity
android:name=".presentation.mvvm.MainActivityMVVM"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
35 changes: 0 additions & 35 deletions app/src/main/java/otus/homework/coroutines/CatsPresenter.kt

This file was deleted.

10 changes: 0 additions & 10 deletions app/src/main/java/otus/homework/coroutines/CatsService.kt

This file was deleted.

32 changes: 0 additions & 32 deletions app/src/main/java/otus/homework/coroutines/CatsView.kt

This file was deleted.

16 changes: 0 additions & 16 deletions app/src/main/java/otus/homework/coroutines/DiContainer.kt

This file was deleted.

24 changes: 0 additions & 24 deletions app/src/main/java/otus/homework/coroutines/Fact.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package otus.homework.coroutines.data

import retrofit2.http.GET

interface CatsService {

@GET("fact")
suspend fun getCatFact(): FactDto
}
10 changes: 10 additions & 0 deletions app/src/main/java/otus/homework/coroutines/data/FactDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package otus.homework.coroutines.data

import com.google.gson.annotations.SerializedName

data class FactDto(
@SerializedName("fact")
val fact: String,
@SerializedName("length")
val length: String
)
14 changes: 14 additions & 0 deletions app/src/main/java/otus/homework/coroutines/data/ImageDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package otus.homework.coroutines.data

import com.google.gson.annotations.SerializedName

data class ImageDto(
@SerializedName("id")
val id: String,
@SerializedName("url")
val url: String,
@SerializedName("width")
val width: Int,
@SerializedName("height")
val height: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package otus.homework.coroutines.data

import retrofit2.http.GET

interface ImageService {

@GET("images/search")
suspend fun getImage(): ArrayList<ImageDto>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше указывать просто List

}
13 changes: 13 additions & 0 deletions app/src/main/java/otus/homework/coroutines/data/RepositoryImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package otus.homework.coroutines.data

import otus.homework.coroutines.domain.Repository

class RepositoryImpl(
private val catsService: CatsService,
private val imageService: ImageService
) : Repository {

override suspend fun getFact(): String = catsService.getCatFact().fact

override suspend fun getImageUrl(): String = imageService.getImage()[0].url
}
36 changes: 36 additions & 0 deletions app/src/main/java/otus/homework/coroutines/di/DiContainer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package otus.homework.coroutines.di

import otus.homework.coroutines.data.CatsService
import otus.homework.coroutines.data.ImageService
import otus.homework.coroutines.data.RepositoryImpl
import otus.homework.coroutines.domain.GetCatModelUseCase
import otus.homework.coroutines.presentation.mvvm.MainViewModel
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class DiContainer {

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

private val factService by lazy { factRetrofit.create(CatsService::class.java) }

private val imageRetrofit by lazy {
Retrofit.Builder()
.baseUrl("https://api.thecatapi.com/v1/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}

private val imageService by lazy { imageRetrofit.create(ImageService::class.java) }

private val repository by lazy { RepositoryImpl(factService, imageService) }

val useCase by lazy { GetCatModelUseCase(repository) }

val mainViewModel by lazy { MainViewModel(useCase) }
}
6 changes: 6 additions & 0 deletions app/src/main/java/otus/homework/coroutines/domain/CatModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package otus.homework.coroutines.domain

data class CatModel(
val fact: String,
val imageUrl: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package otus.homework.coroutines.domain

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext

class GetCatModelUseCase(private val repository: Repository) {

suspend operator fun invoke(): CatModel = withContext(Dispatchers.IO) {
val fact = async { repository.getFact() }
val url = async { repository.getImageUrl() }
CatModel(fact.await(), url.await())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package otus.homework.coroutines.domain

interface Repository {

suspend fun getFact(): String

suspend fun getImageUrl(): String
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package otus.homework.coroutines
package otus.homework.coroutines.presentation

object CrashMonitor {

Expand All @@ -7,4 +7,4 @@ object CrashMonitor {
*/
fun trackWarning() {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package otus.homework.coroutines.presentation.mvp

import kotlinx.coroutines.*
import otus.homework.coroutines.domain.GetCatModelUseCase
import otus.homework.coroutines.presentation.CrashMonitor
import java.net.SocketTimeoutException

class CatsPresenter(
private val catUseCase: GetCatModelUseCase
) {
private var _catsView: ICatsView? = null
private var scope: CoroutineScope? = null

init {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А почему это не сделать при декларации переменной? Тогда не придется с сейфколлами работать

scope = CoroutineScope(Dispatchers.Main + CoroutineName("CatsCoroutine"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Инстанс job не нужен?

}

fun onInitComplete() {
scope?.launch {
try {
val cat = catUseCase.invoke()
_catsView?.populate(cat)
} catch (e: CancellationException) {
throw e
} catch (_: SocketTimeoutException) {
_catsView?.showError()
} catch (t: Throwable) {
CrashMonitor.trackWarning()
}
}
}

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

fun detachView() {
_catsView = null
scope?.cancel()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут не будет исключения тк нет инстанса Job?

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package otus.homework.coroutines.presentation.mvp

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
import otus.homework.coroutines.R
import otus.homework.coroutines.domain.CatModel

class CatsView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr), ICatsView {

var presenter: CatsPresenter? = null

override fun onFinishInflate() {
super.onFinishInflate()
findViewById<Button>(R.id.button).setOnClickListener {
presenter?.onInitComplete()
}
}

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

override fun showError() {
Toast.makeText(this.context, R.string.error, Toast.LENGTH_SHORT).show()
}
}

interface ICatsView {

fun populate(cat: CatModel)

fun showError()
}
Loading