我刚刚学习了rxjava,rxkotlin,dagger和retrofit,但我不知道在与server / db通信时采取的方法以及如何在本地存储信息。 最后有3个问题。请帮忙
@Singleton
class MyInteractor @Inject constructor() {
@Inject lateinit var context: Context
@Inject lateinit var restClient: RestClient
private var subscriptions: MutableList<Disposable> = mutableListOf()
private var settingsSubject: BehaviorSubject<SettingsDTO> = BehaviorSubject.create()
fun initData() {
initSettings()
}
fun unsubscribeAll() {
subscriptions.forEach({ subscription -> subscription.dispose() })
}
private fun initSettings() {
val settingsObservable = restClient.getSettings()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
val settingsServerSubscription = settingsObservable.subscribe({ response ->
run {
settingsSubject.onNext(response.body())
}
}, {
//TODO handle errors
})
subscriptions.add(settingsServerSubscription)
//subscribe database to subject changes
val settingsDatabaseSubscription = settingsSubject.subscribe { setting ->
//TODO save or update db
}
subscriptions.add(settingsDatabaseSubscription)
}
fun getSettings(callback: SettingsCallback) {
callback.onFetchedSettings(settingsSubject.value)
}
}
答案 0 :(得分:0)
- 我是否需要保存一次性主题并取消订阅?或者自动完成? (我将所有订阅保存在列表中,然后立即取消所有订阅)
醇>
是绝对的(这不是自动完成的)。特别是,如果您的订阅者尝试访问某些可能不再存在的对象,例如将应用程序发送到后台时的视图。虽然你的方法没有任何问题,但是Rx已经有了CompositeDisposable
,它正是你所做的。您可以使用CompositeDisposable.add(Disposable)
添加一次性用品,然后使用CompositeDisposable.clear()
来处理所有一次性用品。您还有CompositeDisposable.dispose()
,但这会使复合一次性使用后无法使用,可能不是您想要的。
- 这是正确的做法吗?我正在初始化initData方法中的所有设置,并在创建活动时调用它。数据存储在行为主题(settingsSubject)中,我订阅该主题以保存数据库中的更改,因此每次我想更改设置我正在调用其余客户端然后更新主题(db将更新因为订阅)
醇>
很难说没有全貌。你在这里看到的是一个可以观察到任何变化的数据库。我的意思是,看起来每次设置发生变化都可以在主题中发布内容并触发所有订阅者。如果这是你想要的那么那似乎没问题。如果您想要读取设置一次而不关心更改,直到您返回到屏幕或重新加载它,那么您可以在调用方法getSettings
时简单地使用observable。类似的东西:
fun getSettings(callback: SettingsCallback) {
restClient.getSettings()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ callback.onFetchedSettings(it) })
}
- 在getSettings方法中,我应该使用回调还是只返回settingsSubject值?
醇>
我会说这实际上取决于你想做什么。我更喜欢总是返回一个observable,让调用代码决定做什么:
fun getSettings() =
restClient.getSettings()
.subscribeOn(Schedulers.io())
// In the calling code for example
interactor.getSettings()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(/* use value */)
如果您想保留主题,您仍然可以这样做:
fun getSettings() = settingsSubject.subscribeOn(Schedulers.io())
// In calling code for example
interactor.getSettings()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(/* use value */)
因为您正在使用BehaviorSubject
,所以当有人订阅时,最后一次发出的项目会再次发出,所以这仍然有效。
同样,回调没有错。我个人认为使用这种反应性界面更清洁。