强制暂停函数在一个线程上工作以在后台映射Realm对象

时间:2019-05-27 12:48:17

标签: multithreading kotlin realm kotlin-coroutines

比方说,我需要定期(每3秒)读取一些RealmObject的列表,并且我想将这些对象映射到将用于填充列表内容的简单数据对象。

对于那些想知道的人,有三个原因:

  • 在我的情况下,计算ViewHolder中视图的值和行为(可见性)的复杂性
  • 我想使用ListAdapter,它需要提供DiffUtilCallback并将在UI之外的其他线程上执行,因此无法在其方法中进行所需的计算,因为它们将从没有在其中创建它们的线程。
  • 从Realm删除视图层的依赖项

我不能简单地以简单的方式使用协程,因为协程将从执行中的一个可用线程跳转到另一个线程,因为我(并且确实如此)最终会收到“领域已关闭” 异常。 / p>

我想出的唯一解决方案是使用仅使用一个线程newSingleThreadContext("RealmSingleThreadContext")的调度程序:

class RealmSingleThreadContext {
    val ctx = NewSingleThreadedContext("RealmSingleThreadContext")

    lateinit var realm : Realm

    init {
        // opening Realm connection for thread "RealmSingleThreadContext"
        GlobalScope.launch(ctx) { realm = Realm.getDefaultInstance() }
    }

    fun close() {
        GlobalScope.launch(ctx) { if (!realm.isClosed()) realm.close() }
    }


}

此类通过Dagger作为Singleton提供,最终,在后台,我将有一个线程为整个应用程序进行映射,而我的“ main” viewModel将在其onClosed方法中调用{此类的{1}}方法。

这是我的用法:

close()

唯一的问题是函数class HomeViewModel @Inject constructor(/* other */var realmSingleThreadContext: RealmSingleThreadContext) { var topLiveEventsUI: MutableLiveData<List<EventPreviewUI>> = MutableLiveData(listOf()) fun useRealmInBckg() { viewModeScope.launch(realmSingleThreadContext.ctx) { topLiveEventsUI.postValue(eventsReadUseCase.getTopLiveEvents() .map{ mapper.map(it) } } } } 具有newSingleThreadContext(name: String)批注,因此这意味着它将很快被删除。

我的问题是:除了使用这个废弃的Dispatcher之外,还有谁能提出其他解决方案?

1 个答案:

答案 0 :(得分:1)

使用Java执行程序创建您自己的单线程调度程序非常容易:

$mods = array(); 
foreach($fields as $field) { 
  $mods[$field['name']][] = $field['rating']; 
}

<table>
  <tr>

<?php
if($mods) {
    foreach($mods as $key=>$value) {
?>
    <td><?php echo $key; ?></td>
    <td><?php echo (array_sum($value)/count($value)); ?></td> 
<?php 
    }
}
?>