Транзакции SQLite останавливаются на Dispatchers.Main, но работают на Dispatchers.Default и Dispatchers.IO - PullRequest
1 голос
/ 04 марта 2020

Я работаю над проектом, к которому я, к сожалению, не могу использовать ROOM для доступа к базе данных, потому что он сильно зависит от курсоров, которые читают базы данных, созданные в результате вызовов API

Так что для этой работы я использую обычный SQLiteOpenHelper для получения readableDatabase и выполнения запросов с использованием чего-то вроде

withContext(Dispatchers.IO) { db.execSQL(.....) }

Я столкнулся с проблемой с транзакциями, которые создали взаимоблокировки, например, это может вызвать проблемы

suspend fun readDataFromServer() {
    withContext(dispatchers.IO) { db.beginTransaction() } 
    val inputStream = withContext(dispatchers.IO) { client.getDataStream() }

    while(true) {
       withContext(dispatchers.IO) { //code here that reads from the input stream until it finds a separator 
       }
       withContext(dispatchers.Default) { 
           //code that does some calculations that may take anywhere from 500 to 1500 ms
       }

       withContext(dispatchers.IO) { 
           //code that saves the data in the appropriate form in my db
       }

    }
    withContext(dispatchers.IO) { 
         db.setTransactionSuccessful() 
         db.endTransaction()
    }

}        

(обратите внимание, что вышеприведенный код не совсем подходит для моего фиктивного кода, у меня нет доступа к моему проекту atm)

Я исследовал его, и, похоже, проблема заключалась в том, что транзакция должна start и fini sh в одном и том же потоке, поэтому, когда я использовал withContext для изменения диспетчеров (даже если это был тот же диспетчер), это привело бы к тупику

В конце я решил свою проблему, обернув вся функция в одном с контентом, но я заметил кое-что любопытное

обычно функция начиналась бы примерно так:

* 10 18 *

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

launch(Dispatchers.Default) {
    readDataFromServer()
}

и

launch(Dispatchers.IO) {
    readDataFromServer()
}

оба, кажется, работают

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

заключает его в один и тот же с помощью Context правильный ответ ? или может использовать запуск (Dispatchers.Default) тоже правильно?

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

...