提问者:小点点

强制挂起的函数在一个线程上工作,用于在后台映射领域对象


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

对于那些怀疑的人来说,有三个原因:

  • viewholder中计算视图的值和行为(可见性,即)的复杂度很大,在我的情况下
  • 我想使用ListAdapter,它需要提供DiffutilCallback,该DiffutilCallback将在UI以外的其他线程上执行,因此不可能在其方法中进行所需的计算,因为它们将从未创建它们的线程中使用。
  • 从领域删除视图层的依赖关系

我不能简单地使用从一个可用线程跳转到另一个可用线程的基本方式,因为我将(我确实)最终收到“领域已经关闭”异常。

我想出的唯一解决方案是使用只使用一个线程NewSinglethreadContext(“RealMSinglethreadContext”)的dispatcher,例如:

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作为单例提供的,最终在最后,我将有一个线程在后台为整个应用程序做映射,我的“Main”viewModel将调用它的onClosed方法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)@ObsoleteCoroutineAPI注释,因此这意味着它将很快被删除。

我的问题是:除了使用这个过时的调度器,还有人能提出其他的解决方案吗?


共1个答案

匿名用户

从Java执行器制作自己的单线程调度器是非常容易的:

val singleThreadContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()