-
Notifications
You must be signed in to change notification settings - Fork 239
homework_2: done #1
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 CatImageResponse( | ||
@field:SerializedName("file") | ||
val fileName: String = "" | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,68 @@ | ||
package otus.homework.coroutines | ||
|
||
import kotlinx.coroutines.* | ||
import retrofit2.Call | ||
import retrofit2.Callback | ||
import retrofit2.Response | ||
import java.lang.Exception | ||
import java.net.SocketTimeoutException | ||
|
||
class CatsPresenter( | ||
private val catsService: CatsService | ||
private val catsService: CatsService, | ||
private val imageService: ImageService | ||
) { | ||
|
||
private var _catsView: ICatsView? = null | ||
private val presenterScope = CoroutineScope(Dispatchers.Main + CoroutineName("CatsCoroutine")) | ||
private var factJob: Job? = null | ||
private var refreshJob: Job? = null | ||
|
||
fun onInitComplete() { | ||
catsService.getCatFact().enqueue(object : Callback<Fact> { | ||
|
||
override fun onResponse(call: Call<Fact>, response: Response<Fact>) { | ||
if (response.isSuccessful && response.body() != null) { | ||
_catsView?.populate(response.body()!!) | ||
presenterScope.launch { | ||
factJob?.cancelAndJoin() | ||
factJob = launch { | ||
try { | ||
val result = withContext(Dispatchers.IO) { | ||
catsService.getCatFact() | ||
} | ||
_catsView?.populate(result) | ||
} catch (ex: SocketTimeoutException) { | ||
_catsView?.showErrorDialog(ex.localizedMessage ?: "error") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно в одном catch использовать when блок с проверкой типа исключения |
||
} | ||
catch (ex : Exception) { | ||
CrashMonitor.trackWarning() | ||
} | ||
} | ||
} | ||
} | ||
|
||
override fun onFailure(call: Call<Fact>, t: Throwable) { | ||
CrashMonitor.trackWarning() | ||
fun loadFactAndImage() { | ||
presenterScope.launch { | ||
refreshJob?.cancelAndJoin() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А зачем здесь |
||
refreshJob = launch { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нужна ли здесь эта корутина? Думаю можно ее опустить и сразу внутри корутины запущенной на |
||
val factResult = async(Dispatchers.IO) { catsService.getCatFact() } | ||
val imageResult = async(Dispatchers.IO) { imageService.getCatImage() } | ||
try { | ||
val factWithImage = factResult.await().copy(image = imageResult.await().fileName) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А ты уверен что в таком виде они параллельно запустятся? По-моему сначала отработает первый и потом начнет второй. |
||
_catsView?.populate(factWithImage) | ||
} catch (ex: SocketTimeoutException) { | ||
_catsView?.showErrorDialog(ex.localizedMessage ?: "error") | ||
} | ||
catch (ex : Exception) { | ||
CrashMonitor.trackWarning() | ||
} finally { | ||
_catsView?.stopRefreshing() | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
fun attachView(catsView: ICatsView) { | ||
_catsView = catsView | ||
} | ||
|
||
fun detachView() { | ||
presenterScope.cancel() | ||
_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 { | ||
|
||
@GET("random?animal_type=cat") | ||
fun getCatFact() : Call<Fact> | ||
suspend fun getCatFact(): Fact | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,5 +20,6 @@ data class Fact( | |
@field:SerializedName("user") | ||
val user: String, | ||
@field:SerializedName("updatedAt") | ||
val updatedAt: String | ||
val updatedAt: String, | ||
val image: String = "" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не совсем по теме ДЗ, но я бы советовал делать отдельные 2 ДТО на респонсы и их мержить в одну которая пойдет в другой слой |
||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package otus.homework.coroutines | ||
|
||
import retrofit2.http.GET | ||
|
||
interface ImageService { | ||
@GET("meow") | ||
suspend fun getCatImage(): CatImageResponse | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package otus.homework.coroutines | ||
|
||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import kotlinx.coroutines.* | ||
import java.net.SocketTimeoutException | ||
|
||
class MainViewModel( | ||
private val catsService: CatsService, | ||
private val imageService: ImageService | ||
) : ViewModel() { | ||
|
||
val resultLiveData = MutableLiveData<Result>() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не по теме ДЗ, но наружу должна торчать имутабельная |
||
private var factJob: Job? = null | ||
private var refreshJob: Job? = null | ||
private val handler = CoroutineExceptionHandler { _, exception -> | ||
CrashMonitor.trackWarning() | ||
} | ||
|
||
fun onInitComplete() { | ||
viewModelScope.launch(Dispatchers.IO + handler) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тебе здесь можно не переключать контекст. Достаточно переключить в |
||
factJob?.cancelAndJoin() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно убрать |
||
factJob = launch { | ||
try { | ||
val result = withContext(Dispatchers.IO) { | ||
catsService.getCatFact() | ||
} | ||
resultLiveData.postValue(Result.Success(result)) | ||
} catch (ex: SocketTimeoutException) { | ||
resultLiveData.postValue(Result.Error(ex.localizedMessage ?: "error")) | ||
} | ||
} | ||
} | ||
} | ||
|
||
fun loadFactAndImage() { | ||
viewModelScope.launch(Dispatchers.IO + handler) { | ||
refreshJob?.cancelAndJoin() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно убрать |
||
refreshJob = launch { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лишняя корутина |
||
val factResult = async { catsService.getCatFact() } | ||
val imageResult = async { imageService.getCatImage() } | ||
try { | ||
val factWithImage = factResult.await().copy(image = imageResult.await().fileName) | ||
resultLiveData.postValue(Result.Success(factWithImage)) | ||
} catch (ex: SocketTimeoutException) { | ||
resultLiveData.postValue(Result.Error(ex.localizedMessage ?: "error")) | ||
} | ||
} | ||
} | ||
} | ||
|
||
sealed class Result { | ||
data class Success(val data: Fact) : Result() | ||
data class Error(val message: String) : Result() | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Почему решил создать еще одну корутину с таким же контекстом, а контекст переключил внутри? Я думаю достаточно просто переключения через
withContext