Jetpack 与 RxJava2 和 Realm 组合

Jetpack compose with RxJava2 and Realm

我正在开发一个新的 android 应用程序,它使用 Jetpack Compose (1.0.0-alpha08) 和 RxJava2 来管理来自我的模型(在本例中为 Realm 10)的数据流。对于给定的屏幕,我有一个视图模型,它定义了顶级 Compostable 视图将订阅的数据。因此,例如:

ViewModel...

class ListItemViewModel: ViewModel() {
   val items: Flowable<Item>
       get() {
          val data1 = userRealm.where<Item1>()
             .also(query).findAllAsync().asFlowable()
             .onBackpressureLatest().doOnNext{System.out.println("Realm on Next")}
            .observeOn(
                Schedulers.single()
            ).filter{it.isLoaded}.map{ result ->
                System.out.println("Maping Realm")
                result
            }.doOnSubscribe {System.out.println("Subscribe")}
          val data2 == //same as above but with a different item

          return Flowable.combineLatest(data1, data2, combineFunction)
             .onBackpressureLatest()
             .doOnNext{System.out.println("Hello")}
             .doOnComplete {System.out.println("Complete")}
             .subscribeOn(AndroidSchedulers.mainThread())
       }
}

查看

@Compostable
fun List(List<Item> items) {
   val viewModel: ListItemViewModel = viewModel()
   val list by viewModel.items.subscribeAsState(initial = listOf())
   ItemList(list = list)
}

@Compostable
fun ItemList(List<Item> items {
   LazyColumnFor(...) {
     .......
   }
}

一切如我所愿,列表按我的意愿呈现在屏幕上。但是,我假设这里会发生的是订阅只会发生一次,并且 Flowable 只会在发出新数据时推出新数据。因此,我只希望在流中出现新数据时触发各种 onNext 方法,例如领域数据库发生了一些变化。因为我不是 adding/deleting 任何数据 to/from 领域,所以一旦我有了第一组结果,我希望 flowable 会“沉默”。

但是,当我 运行 上面的内容时,与领域订阅相关的订阅消息被一遍又一遍地记录下来。 onNext 方法中的“Hello”和其他日志语句也是如此。此外,如果我在组合函数中添加任何日志记录,我会以与“Hello”日志相同的方式查看这些日志语句。由此看来,每次渲染 List 可组合项时,它都会从我的视图模型重新订阅 Flowable 并触发整个过程。正如我所说,我原以为这种订阅只会发生一次。

这也许是正确的行为,但在精神上,感觉我无缘无故地燃烧 CPU 个循环,因为当没有数据发生变化时我的方法被一遍又一遍地调用。我的设置是否正确,或者我的配置方式是否存在缺陷?

我最终解决了这个问题,并采用了一种混合方法,我使用 Realm/RXJava 来处理数据流,当事情发生变化时,更新一个 LiveData 对象。

查看模型

private val internalItemList = MutableLiveData(listOf<Item>())
val itemList: LiveData<List<Item>> = internalItemList

//capture the subscription so you can dispose in onCleared()
val subscription = items.observeOn(AndroidSchedulers.mainThread()).subscribe {
    this.internalItemList.value = it
}

查看

val list by viewModel.itemList.observeAsState(listOf())

这一定不那么啰嗦,而且可以按我想要的方式工作。不确定这样做是否正确,但它似乎有效