WithContext (Dispatchers.IO) как использовать для комнаты

В нашем приложении так много запросов, и теперь мы используем ROOM, я хочу подтвердить, что это правильный способ использования Coroutine, прежде чем мы использовали это

В Дао

  @Query("SELECT * FROM VISITS")
    suspend fun getAllVisits(): List<Visits>

И мы получаем вот так

fun getAll(visit: Visits?) = runBlocking {
        Log.i(TAG, "addOrUpdateRecord")
        try {

val list = ArrayList<Visits>()
                list.addAll(async {
                    visitsDao.getAllVisits()
                }.await())

}

Но в какой-то статье я читал, что блокировка запуска предназначена только для тестирования, а не для производства, пожалуйста, направьте меня правильным образом Спасибо

Вы можете использовать либо launch {}, либо withContext (io) {} <- этот тип возврата

Yehezkiel L 30.03.2021 09:05

Я не могу использовать withcontext без runblocker.

bakhtiyar hussain 30.03.2021 09:14

вам нужно создать класс, расширяющий ViewModel (), и просто реализовать @Glenn Sandoval. подробнее здесь developer.android.com/topic/libraries/architecture/viewmodel

Yehezkiel L 30.03.2021 09:17
0
3
78
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать что-то вроде этого

GlobalScope.launch { 
            withContext(Dispatchers.IO){
                // your query
            }
        }

на основе ответов @Chirag Rayani, если вы используете viewModel, вы можете использовать viewModelScope.launch {withContext (dispatchers.IO)} и объединить его с liveata.postValue ()

Yehezkiel L 30.03.2021 09:06

если вы используете viewModelScope и скажете, что вы обновляете одну строку в db, и перед обновлением строки вы переключаетесь на другое действие, тогда вы можете получить исключение или данные могут не обновиться в db. поэтому я думаю, что лучше использовать GlobalScope @Yehezkiel L

Chirag Rayani 30.03.2021 09:08

пока viewModel прикреплен к жизненному циклу активности или фрагмента, он все еще в порядке cmiiw

Yehezkiel L 30.03.2021 09:10

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

bakhtiyar hussain 30.03.2021 09:13
Ответ принят как подходящий

Если вам нужна область сопрограммы для запуска сопрограммы, у вас есть lifecycleScope или viewModelScope, готовые к использованию в соответствии с вашими потребностями.

Внутри действия:

fun myMethod() {
    lifecycleScope.launch {
        val list = visitsDao.getAllVisits()
        //Do something with list here
            ...
    }
}

Внутри фрагмента:

fun myMethod() {
    viewLifecycleOwner.lifecycleScope.launch {
        val list = visitsDao.getAllVisits()
        //Do something with list here
            ...
    }
}

Внутри ViewModel:

fun myMethod() {
    viewModelScope.launch {
        val list = visitsDao.getAllVisits()
        //Do something with list here
        ...
    }
}

Внутри обычного класса:

class MyPresenter: CoroutineScope {
    private val myJob = Job()
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Default + myJob
    
    ...

    fun myMethod() {
        launch {
            val list = visitsDao.getAllVisits()
            //Do something with list here
            ...
        }
    }
    
    ...

    //Call clear when required
    fun clear() {
        this.myJob.cancel()
    }
}

Наш шаблон проектирования - MVP, но я могу использовать этот метод?

bakhtiyar hussain 30.03.2021 09:18

@bakhtiyarhussain Вы можете реализовать CoroutineScope в Presenter следующим образом: class MyPresenter: CoroutineScope by MainScope(){ ... }. Используйте подходящий Диспетчер в соответствии с вашими потребностями или создайте его CoroutineContext самостоятельно, без делегирования. Только будьте осторожны, чтобы правильно отменить его прицел

Glenn Sandoval 30.03.2021 09:26

если я реализую CoroutineScope, как вы делаете в презентаторе в моем tableHelperClass, и использую запуск (Dispatchers.IO) при выполнении моих запросов, это хорошая практика?

bakhtiyar hussain 01.04.2021 12:25

@bakhtiyarhussain Если вы добавите ключевое слово suspend в свой метод DAO, вам не нужно беспокоиться о диспетчере, который выполняет вызов. Room выполнит запрос в фоновом потоке.

Glenn Sandoval 01.04.2021 12:35

так что мне просто нужно использовать запуск? и это правильный способ, о котором я упоминаю?

bakhtiyar hussain 01.04.2021 12:37

и как отменить выполнение длинного запроса, если пользователь нажал и перешел к другому действию, как отменить выполняющийся запрос?

bakhtiyar hussain 01.04.2021 12:40

@bakhtiyarhussain launch будет работать на диспетчере coroutineContext. Просто убедитесь, что вы создали CoroutineContext с правильным диспетчером, и когда вам нужно изменить диспетчер внутри функции, вы можете использовать withContext. В вашем случае достаточно просто пометить метод DAO как приостановленный. Как я уже упоминал, Room выполнит запрос в фоновом потоке.

Glenn Sandoval 01.04.2021 12:42

@bakhtiyarhussain Чтобы отменить выполнение, просто вызовите cancel в задании или в CoroutineScope. Посмотрите на метод clear, который я сделал.

Glenn Sandoval 01.04.2021 12:44

в презентаторе мы не используем myJob, а просто используем для отмены?

bakhtiyar hussain 01.04.2021 13:08

@bakhtiyarhussain Один из элементов CoroutineContext - это Job. Каждый вызов launch возвращает задание. Используйте это задание для cancel сопрограммы. В MyPresenter я создаю задание, которое использую для построения CoroutineContext, и использую это задание для отмены всего, используя преимущества структурированного параллелизма.

Glenn Sandoval 01.04.2021 13:23

Я делаю то же самое и использую this.myjob.cancel, но работа не отменяется

bakhtiyar hussain 01.04.2021 13:43

@bakhtiyarhussain Сделать сопрограммы совместимыми с отменой. Это может помочь вам понять, как работают сопрограммы: kotlinlang.org/docs/cancellation-and-timeouts.html

Glenn Sandoval 01.04.2021 13:51

пожалуйста, посмотрите stackoverflow.com/questions/66914896/…

bakhtiyar hussain 02.04.2021 08:37

Большое спасибо, @Glenn Sandoval, вы решили мою проблему

bakhtiyar hussain 02.04.2021 15:03

В Viewmodel:

viewmodelScope.launch(Dispatchers.IO){
  visitsDao.getAllVisits()
}

ИЛИ другая функция приостановки

suspend fun addAll() {
    visitsDao.getAllVisits().run{
     ArrayList<Visits>().addAll(this)

   }
}

EvenMore, просто используйте поток, и вы можете сделать это с помощью Live Data Builder / map / asLiveData и т. д.

посмотрите плз stackoverflow.com/questions/66914896/…

bakhtiyar hussain 02.04.2021 10:53

Да, я это видел. И вот мой результат, запускать блокировку не рекомендуется. Проверьте ссылка на сайт. «Основной поток, вызывающий runBlocking, блокирует, пока сопрограмма внутри runBlocking не завершится». Если у вас нет ViewModel, просто используйте MainScope (), который может быть отменен, когда вид будет уничтожен. И вы можете создать свой собственный, просто используя SupervisorJob () + Диспетчеры.Главная.

lee 02.04.2021 13:11

Кстати, я привык использовать MainScope до того, как Google создал viewModelScope и lifecycleScope. Проверить kotlinx.coroutines / -main-scope

lee 02.04.2021 13:15

Другие вопросы по теме

Похожие вопросы

Как мне заставить recyclerView Pinch масштабировать несколько дочерних элементов с помощью событий щелчка для каждого дочернего элемента?
Невозможно создать адаптер вызова для класса java.lang.Object - дооснащение
Ошибка компиляции: невозможно получить доступ к com.prolificinteractive.materialcalendarview.OnDateSelectedListener, который является супертипом
Получение ошибки при попытке запустить приложение для Android с помощью флаттера
Добавлена ​​зависимость, по-прежнему показывающая класс или интерфейс, ожидаемый в случае ViewModel в студии Android
Retrofit2: - Нужно ли мне закрывать соединение, если добавлен собственный перехватчик?
Ошибка КЛАССА АДАПТЕРА отображается в LOGCAT, а ДАННЫЕ не отображаются в RECYCLERVIEW
Как увеличить размер кнопки при нажатии кнопки? пожалуйста, помогите мне
Исключение Java.outOfMemory в простом приложении
Как решить ANDROID_SDK_ROOT = undefined (рекомендуемая настройка) и ANDROID_HOME = undefined (УСТАРЕЛО)