-
Notifications
You must be signed in to change notification settings - Fork 239
ДЗ 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
base: development
Are you sure you want to change the base?
Conversation
app/build.gradle
Outdated
//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" |
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.
Несколько последних версий ретрофита поддерживают саспенд функции, так что этот адаптер уже не нужен
} | ||
}) | ||
|
||
//++++++++++++++++++++++++++++ |
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.
Комментарии лучше убрать)
/* | ||
### Реализовать решение ViewModel | ||
*/ | ||
viewModel = CatsViewModel(diContainer.serviceFact, diContainer.serviceImage) |
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.
Тут неправильное использование ViewModel
. Основная идея ViewModel
в том что она умеет переживать пересоздание активити, достигается это за счет хранилища ViewModel
. Поэтому есть определенные требования к тому как их создавать. Создавать их правильно не через конструктор, а через фактори метод ViewModelProviders.of
Так ты привязываешь ViewModel
к LifecycleOwner
. И последний момент - чтобы создать ViewModel
с не дефолтным конструктором ты должен реализовать Factory.
public class CatsViewModel extends ViewModelProvider.NewInstanceFactory {
private String name;
public CatsViewModel(String name) {
super();
this.name = name;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (modelClass == CatsViewModel.class) {
return (T) new CatsViewModel(name);
}
return null;
}
}
) { | ||
|
||
private var _catsView: ICatsView? = null | ||
private val presenterScope = | ||
PresenterScope(Job(), Dispatchers.Main, CoroutineName("CatsCoroutine")) |
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.
Здесь можно Job
не указывать. Имеет смысл если ты хочешь передать уже созданную Job
в дочерний контекст или если хочешь передать SupervisorJob
} | ||
} | ||
|
||
private suspend fun getCatFactResponse(): Fact { |
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.
Эти функции лишние. Лучше их удалить.
import kotlinx.coroutines.launch | ||
|
||
class CatsViewModel( | ||
private val catsServiceFact: CatsService, |
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.
Опять лишний класс-зависимость
get() = _catsResponse | ||
|
||
fun getCatFactImage(){ | ||
viewModelScope.launch(SupervisorJob() + CoroutineExceptionHandler{ |
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.
У viewModelScope
уже есть SupervisorJob
в качестве элемента контекста
} | ||
} | ||
|
||
private suspend fun getCatFactResponse(): Fact { |
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.
Ненужные функции
try { | ||
val factResponse = getCatFactResponse() | ||
val imageResponse = getCatImageResponse() | ||
if (factResponse != null && imageResponse != null) { |
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.
Они не могут быть null
coroutineContext, throwable -> CrashMonitor.trackWarning() | ||
}) { | ||
try { | ||
val factResponse = getCatFactResponse() |
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.
У тебя не параллельные запросы. Сначала вызывается первый и корутина саспендится. После того как он заканчивается и она резьюмится начинает работать второй. Используй async
чтобы распараллелить
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.
Вопрос: изначально я сделал без async чтобы они выполнялись полседовательно
чтобы два результата использовать при создании объекта
FactImage(factResponse, imageResponse)
теперь при использовании async как это будет работать?
допустим получаем результат factResponse, imageResponse - неодновременно
FactImage(factResponse, imageResponse) будет создан из того что пришло первым,
а второй параметр "уйдет" пустым
или
родительская корутину (которая запускает launch)
"дождется" всех и только потом создаст FactImage(factResponse, imageResponse) ?
Привет. Посмотрел правки. Работу принимаю, но пожалуйста поправь первое замечание про диспатчеры) |
val imageResponse = getCatImageResponse() | ||
if (factResponse != null | ||
&& imageResponse != null ) { | ||
withContext(Dispatchers.IO) { |
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.
Не совсем понял зачем тебе тогда launch с Dispatchers.Main
если ты все тело выполняешь на Dispatchers.IO
|
||
/** | ||
* antonkazakov: ... Используй async чтобы распараллелить | ||
* Вопрос: изначально я сделал без async чтобы они выполнялись полседовательно |
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.
Ты можешь сам это проверить на простейшем примере. Такие вещи лучше проверять самому чтобы не забывать и понимать.
Пустого параметра не будет. У тебя корутина будет сасаспендена пока не выполнится await
вернул catsServiceImage: CatsService в аргументы CatsViewModel так как он нужен для вызова другого url для подгрузки фото |
ДЗ Coroutines
Исполнитель Мустафа Шокан