Skip to content

ДЗ Coroutines #3

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 4 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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: 0 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ dependencies {
//coroutine retrofit
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines"
implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:$retrofit_coroutines_adapter"
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
}
47 changes: 19 additions & 28 deletions app/src/main/java/otus/homework/coroutines/CatsPresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package otus.homework.coroutines
import android.util.Log
import kotlinx.coroutines.*
import retrofit2.Response
import java.net.SocketTimeoutException
import kotlin.coroutines.CoroutineContext

class CatsPresenter(
Expand All @@ -12,39 +13,32 @@ class CatsPresenter(

private var _catsView: ICatsView? = null
private val presenterScope =
PresenterScope(Job(), Dispatchers.Main, CoroutineName("CatsCoroutine"))
PresenterScope(Dispatchers.Main, CoroutineName("CatsCoroutine"))

fun onInitComplete() {
presenterScope.launch {
try {
val factResponse = getCatFactResponse()
val imageResponse = getCatImageResponse()
if (factResponse != null
&& imageResponse != null ) {
withContext(Dispatchers.IO) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Не совсем понял зачем тебе тогда launch с Dispatchers.Main если ты все тело выполняешь на Dispatchers.IO

try {
val factResponse = catsServiceFact.getCatFact()
val imageResponse = catsServiceImage.getCatImage()
val factImage = FactImage(factResponse, imageResponse)
_catsView?.populate(factImage)
} else
CrashMonitor.trackWarning()

} catch (e: java.net.SocketTimeoutException) {
_catsView?.showToast("Не удалось получить ответ от сервером")
} catch (e: Exception) {
_catsView?.showToast(e.message.toString())
e.printStackTrace()
} catch (e: Exception) {
when (e) {
is SocketTimeoutException -> {
_catsView?.showToast("Не удалось получить ответ от сервером")
}
else -> {
_catsView?.showToast(e.message.toString())
CrashMonitor.trackWarning()
e.printStackTrace()
}
}
}
}

}
}

private suspend fun getCatFactResponse(): Fact {
return catsServiceFact.getCatFact()
}


private suspend fun getCatImageResponse(): Image {
return catsServiceImage.getCatImage()
}

fun attachView(catsView: ICatsView) {
_catsView = catsView
}
Expand All @@ -56,12 +50,9 @@ class CatsPresenter(
}

class PresenterScope(
private val job: Job,
private val dispatchers: CoroutineDispatcher,
private val coroutineName: CoroutineName
) : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = job + dispatchers + coroutineName


get() = dispatchers + coroutineName
}
72 changes: 42 additions & 30 deletions app/src/main/java/otus/homework/coroutines/CatsViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,58 +1,70 @@
package otus.homework.coroutines

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.net.SocketTimeoutException

class CatsViewModel(
private val catsServiceFact: CatsService,
private val catsServiceImage: CatsService
): ViewModel() {
private val catsService: CatsService
) : ViewModel() {
private var _catsResponse = MutableLiveData<Result<FactImage>>()
val catsResponse: LiveData<Result<FactImage>>
get() = _catsResponse

fun getCatFactImage(){
viewModelScope.launch(SupervisorJob() + CoroutineExceptionHandler{
coroutineContext, throwable -> CrashMonitor.trackWarning()
fun getCatFactImage() {
viewModelScope.launch(CoroutineExceptionHandler { coroutineContext, throwable ->
CrashMonitor.trackWarning()
}) {
try {
val factResponse = getCatFactResponse()
val imageResponse = getCatImageResponse()
if (factResponse != null && imageResponse != null) {
val factImage = FactImage(factResponse, imageResponse)
_catsResponse.value = Result.Success(factImage)
} else{
_catsResponse.value = Result.Error("Что то пошло не так", null)
}
val factResponseDeferred = async {catsService.getCatFact()}
val imageResponseDeferred = async {catsService.getCatImage()}

val factResponse = factResponseDeferred.await()
val imageResponse = imageResponseDeferred.await()

/**
* antonkazakov: ... Используй async чтобы распараллелить
* Вопрос: изначально я сделал без async чтобы они выполнялись полседовательно
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ты можешь сам это проверить на простейшем примере. Такие вещи лучше проверять самому чтобы не забывать и понимать.

Пустого параметра не будет. У тебя корутина будет сасаспендена пока не выполнится await

* чтобы два результата использовать при создании объекта
* FactImage(factResponse, imageResponse)
* теперь при использовании async как это будет работать?
* допустим получаем результат factResponse, imageResponse - неодновременно
* FactImage(factResponse, imageResponse) будет создан из того что пришло первым,
* а второй параметр "уйдет" пустым
* или
* родительская корутину (которая запускает launch)
* "дождется" всех и только потом создаст FactImage(factResponse, imageResponse) ?
*/
val factImage = FactImage(factResponse, imageResponse)
_catsResponse.value = Result.Success(factImage)

} catch (e: java.net.SocketTimeoutException) {
_catsResponse.value = Result.Error("Не удалось получить ответ от сервером", e)
} catch (e: Exception) {
_catsResponse.value = Result.Error(e.message.toString(), e)
e.printStackTrace()
when (e) {
is SocketTimeoutException -> {
_catsResponse.value =
Result.Error("Не удалось получить ответ от сервером", e)
}
else -> {
_catsResponse.value = Result.Error(e.message.toString(), e)
e.printStackTrace()
}
}
}
}
}

private suspend fun getCatFactResponse(): Fact {
return catsServiceFact.getCatFact()
}


private suspend fun getCatImageResponse(): Image {
return catsServiceImage.getCatImage()
}
}

sealed class Result<out T>{
data class Success<out R>(val value: R): Result<R>()
sealed class Result<out T> {
data class Success<out R>(val value: R) : Result<R>()
data class Error(
val message: String,
val throwable: Throwable?
): Result<Nothing>()
) : Result<Nothing>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package otus.homework.coroutines

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider

class CatsViewModelFactory(private val catsService: CatsService): ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = CatsViewModel(catsService) as T
}
3 changes: 1 addition & 2 deletions app/src/main/java/otus/homework/coroutines/DiContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class DiContainer() {
.build()
}

val serviceFact by lazy { retrofitFact.create(CatsService::class.java) }
val serviceImage by lazy { retrofitImage.create(CatsService::class.java) }
val service by lazy { retrofitFact.create(CatsService::class.java) }

}
5 changes: 3 additions & 2 deletions app/src/main/java/otus/homework/coroutines/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.squareup.picasso.Picasso

Expand All @@ -25,7 +26,8 @@ class MainActivity : AppCompatActivity() {
/*
### Реализовать решение ViewModel
*/
viewModel = CatsViewModel(diContainer.serviceFact, diContainer.serviceImage)
val viewModelFactory = CatsViewModelFactory(diContainer.service)
viewModel = ViewModelProvider(this, viewModelFactory).get(CatsViewModel::class.java)

viewModel.getCatFactImage()

Expand All @@ -48,7 +50,6 @@ class MainActivity : AppCompatActivity() {
}
})

//++++++++++++++++++++++++++++
/*
### Перейти с коллбеков на саспенд функции и корутины
### Добавить к запросу фактов запрос рандомных картинок с [https://aws.random.cat/meow](https://aws.random.cat/meow)
Expand Down