Сопрограммный распределитель на петлевой нити

#android #multithreading #realm #kotlin-coroutines

#Android #многопоточность #kotlin #область #kotlin-сопрограммы

Вопрос:

У меня есть вспомогательный класс для выполнения некоторых заданий в области базы данных. Как вы знаете, у нас есть некоторые ограничения в работе с realm, такие как:

  1. Экземпляр Realm не обновляется автоматически в потоке без цикла.
  2. Доступ к объектам области возможен только в том потоке, в котором они были созданы

Мой вспомогательный класс расширяется CoroutineScope и обеспечивает CoroutineContext Я использовал этот код Executors.newSingleThreadExecutor().asCoroutineDispatcher()

Но моя проблема в том, что все задания в этом CoroutineScope выполняются в потоке без цикла, так как я могу создать ExecutorCoroutineDispatcher поток, который выполняется в одном циклическом потоке.

Очевидно, что я не хочу использовать Dispatchers.Main , потому что он предполагает выполнение заданий в моей базе данных

Комментарии:

1. Как насчет того, чтобы создать a val handlerThread = HandlerThread(name) , запустить его, затем создать обработчик поверх его looper и преобразовать его в dispatcher: Handler(handlerThread.looper).asCoroutineDispatcher()

2. @Pawel Я уже проверял это, но он выдает это исключение Caused by: java.lang.NullPointerException: Attempt to read from field 'android.os.MessageQueue android.os.Looper.mQueue' on a null object reference

3. К сожалению, вы правы. Я не запускал поток обработчика.

Ответ №1:

Хотя проблема OP уже решена комментарием @Pawel, для тех, кому может понадобиться определенный фрагмент кода:

 // prepare a HandlerThread and start it
val handlerThread = HandlerThread("MyThread")
handlerThread.start()
// obtain Handler from the HandlerThread's looper
val handler = Handler(handlerThread.looper)
// Now you can get CoroutineDispatcher from the Handler
val myDispatcher = handler.asCoroutineDispatcher()
 

Или вкратце с использованием функций области видимости:

 val myDispatcher = HandlerThread("MyThread")
    .apply { start() }
    .looper.let { Handler(it) }
    .asCoroutineDispatcher()