#android #kotlin-coroutines
Вопрос:
Контекст
Я пытаюсь обновить пару фоновых заданий в Android 6. Основная цель состоит в том, чтобы сделать работу, выполняемую с помощью фонового задания, легкой и без блокировки потоков пользовательского интерфейса. Поэтому я решил кое-что сделать:
- GlobalScope может быть плохой идеей, так как умирающий поток завершит остальные. Так что сопрограмма поможет вам в этом
- Поскольку мне нужны операции ввода-вывода и сетевые функции, мне нужен пул потоков, предназначенный для этих задач. Поэтому я буду использовать Dispatchers.IO
- Работа связанных служб занятости предназначена для «увольнения и забвения». Приложению все равно — поэтому я просто запущу задание, вместо того чтобы ждать вывода асинхронного
Код
Все вместе я разработал следующий класс JobService в качестве шаблона для других, которые будут перенесены или реализованы. Поскольку задание отменено, класс вернет унаследованным функциям значение false.
import android.app.job.JobParameters
import android.app.job.JobService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class TestJobService : JobService() {
override fun onStartJob(params: JobParameters?): Boolean {
CoroutineScope(Dispatchers.IO).launch {
// Fire and Forget
}
return false
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
}
Вопросы
Если вы хотите ответить, пожалуйста, используйте номер вопроса.
- Является ли сопрограмма хорошей идеей?
- Я получаю ошибки из основного потока «I/art: Примечание: время окончания превышает эпоху:» — это сбивает с толку и может указывать на то, что служба заданий выполняет большую работу в потоке пользовательского интерфейса. Но у меня нет ошибок от хореографа, которые обычно должны иметь место, если пользовательский интерфейс в беде.
- Это плохая идея возвращать false в функциях JobService
Используемые в настоящее время Ссылки
https://medium.com/androiddevelopers/coroutines-on-android-part-i-getting-the-background-3e0e54d20bb
https://medium.com/androiddevelopers/coroutines-on-android-part-ii-getting-started-3bff117176dd
https://medium.com/androiddevelopers/coroutines-on-android-part-iii-real-work-2ba8a2ec2f45
https://developer.android.com/kotlin/coroutines/coroutines-adv?hl=de#coroutinescope
https://kotlinlang.org/docs/coroutines-basics.html#extract-function-refactoring
Ответ №1:
- Единственное, что делает ваше использование
CoroutineScope
, — это предоставляетIO
диспетчера. В нынешнем виде, если какая-либо работа, выполненная в сопрограмме, вызовет исключение, вся область будет отменена. Это может быть проблемой, если вы запускаете несколько сопрограмм из него. Если вы действительно заботитесь об этом, вам также нужно будет настроить его сSupervisorJob
помощью :CoroutineScope(Dispatchers.IO) SupervisorJob()
. - Трудно определить значение этой ошибки без вашего фактического кода. Из быстрого исследования, если вы сделаете что-то, что должно происходить только в основном потоке (например, возможно, доступ к определенным компонентам Android), это может привести к этой ошибке. Возможно, проверьте свой код на наличие таких случаев и заверните его в:
withContext(Dispatchers.Main) { ... }
Но опять же, это всего лишь предположение без какого-либо фактического кода.
- В документах указано, что для
onStartJob
:
Система удерживает блокировку от имени вашего приложения до тех пор, пока выполняется ваша работа. Эта блокировка срабатывания приобретается до вызова этого метода и не освобождается до тех пор, пока вы не вызовете jobFinished(логические параметры android.app.job.job) или после того, как система вызовет onStopJob(параметры android.app.job.job), чтобы уведомить вашу работу о преждевременном закрытии.
Возврат false из этого метода означает, что ваша работа уже завершена. Блокировка пробуждения системы для задания будет выпущена, и onStopJob(параметры android.app.job.job) не будет вызываться.
И согласно документам wakelock,
Блокировка пробуждения — это механизм, указывающий, что вашему приложению необходимо, чтобы устройство оставалось включенным.
Так что нет, кажется неправильным возвращаться false
из onStartJob
, так как JobService
не будет должным образом поддерживать wakelock. Чтобы исправить это, вы должны вернуться true
из этого метода, и по завершении сопрограммы вы должны позвонить jobFinished
, чтобы указать, что задание выполнило всю свою работу.
Для onStopJob
возвращаемых значений:
значение true указывает менеджеру по работе, хотите ли вы перенести это задание на основе критериев повторной попытки, предоставленных во время создания задания; или значение false, чтобы полностью завершить задание. Независимо от возвращенного значения, ваше задание должно прекратиться.
В этом случае трудно определить правильное значение на основе вашего фрагмента. Вы должны быть в состоянии определить, что правильно, исходя из вашего варианта использования. В этом методе вы должны отменить ранее созданные CoroutineScope
. Для этого вам нужно будет сохранить ссылку на область действия.