Комната allowMainThreadQueries с сопрограммами Kotlin - PullRequest
0 голосов
/ 04 февраля 2019

Официальная документация Android гласит, что использование allowMainThreadQueries() не рекомендуется, так как это может заблокировать пользовательский интерфейс на длительный период времени и вызвать ANR.Но сопрограммы Kotlin дали нам возможность выполнить некоторую операцию в главном потоке без эффективной блокировки пользовательского интерфейса.

Поэтому я спрашиваю: безопасно ли использовать allowMainThreadQueries() и обращаться к базе данных вобласть действия программы, работающая в главном потоке? Как в следующем:

// WITH allowMainThreadQueries()
val activityJob = Job()
val mainScope = CoroutineScope(Dispatchers.Main + activityJob)
mainscope.launch {

    // access room database and retrieve some data

    // update UI with data retrived

}

Или мы должны придерживаться старого способа не разрешать запросы основного потока и выполнять запросы к базе данных в другом потоке?

// WITHOUT allowMainThreadQueries()
val activityJob = Job()
val defaultScope = CoroutineScope(Dispatchers.Default + activityJob)
val mainScope = CoroutineScope(Dispatchers.Main + activityJob)
defaultScope.launch {

    // access room database and retrieve some data

    mainScope.launch {
        // update UI with data retrived
    }

}

Я спрашиваю, потому что прежний способ (с allowMainThreadQueries()):

  • гораздо более читабелен (я могу обновить пользовательский интерфейс в том же контексте сопрограммы функций, которые обращаются кбаза данных, не имея отношения к запуску обновлений пользовательского интерфейса в другой области сопрограмм)
  • позволяет упростить обработку ошибок
  • использует только одну область сопрограмм (поэтому меньше областей, о которых нужно заботиться)

1 Ответ

0 голосов
/ 04 февраля 2019

Вам не нужно allowMainThreadQueries(), чтобы это работало.Сопрограмма с заданной областью выполняется в своем потоке.

Это то, что я не так давно сделал:

@UiThread
fun getUsers(context: Context): LiveData<List<User>> {
    if (!::users.isInitialized) {
        users = MutableLiveData()
        users.postValue(MyDatabase.get(context).users().getAll())
        GlobalScope.launch(Dispatchers.Main) {
            val usersFromDb: List<User> = async(Dispatchers.IO) {
                return@async MyDatabase.get(context).users().getAll()
            }.await()
            users.value = usersFromDb
        }
    }
    return users
}

Вы можете видеть, что этот метод getUsers() вызывается из основного потока, возвращая LiveData (что удобно в этом случае).Запрос к базе данных происходит в GlobalScope.launch().

Так что да, ваш дизайн мне нравится лично.И тот, который работает.Но я не думаю, что вам вообще понадобится allowMainThreadQueries().Не стесняйтесь читать (мой) пост в блоге: https://proandroiddev.com/android-viewmodel-livedata-coroutines-contraption-e1e44af690a6

...