与服务器和数据库通信时,在 android 中使用 rxkotlin 或 rxjava 的正确方法是什么?

What is the right approach using rxkotlin or rxjava in android when communicating with server and db?

刚刚学习了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)
}
}
  1. 我是否需要保存一次性主题并取消订阅?还是自动完成? (我将所有订阅保存在一个列表中,然后一次性全部取消)
  2. 这是正确的方法吗?我正在初始化 initData 方法中的所有设置,并在创建 activity 时调用它。 数据存储在行为主题 (settingsSubject) 中,我订阅该主题以保存数据库中的更改, 所以每次我想更改设置时,我都会调用其余客户端,然后更新主题(数据库将因订阅而更新)
  3. 在 getSettings 方法上,我应该使用回调还是只使用 return settingSubject 值?
  1. Do I need to save the Disposable subjects and unsubscribe? Or is done automatically? (I'm saving all of the subscriptions in a list then undispose all at once)

绝对是(它不是自动完成的)。特别是如果您的订阅者尝试访问某些可能不再存在的对象,例如当您将应用程序发送到后台时的视图。尽管您的方法没有任何问题,但 Rx 已经有一个 CompositeDisposable 可以完全满足您的要求。您可以使用 CompositeDisposable.add(Disposable) 添加一次性用品,然后使用 CompositeDisposable.clear() 处理所有一次性用品。您也有 CompositeDisposable.dispose(),但这会导致复合一次性材料之后无法使用,并且可能不是您想要的。

  1. Is this the right approach? I'm initializing all settings in the initData method, and call it at creation of an activity. The data is stored in a behaviour subject (settingsSubject) and I subscribe on that subject to save changes in database, so everytime I want to change a setting I'm calling the rest client and then update the subject (db will be updated because of the subscription)

没有全貌很难说。您在此处拥有的内容看起来像一个可以观察任何更改的数据库。我的意思是,看起来每次设置发生变化时,您都可以 post 主题中的某些内容并触发其所有订阅者。如果这是你想要的,那似乎没问题。如果您只想读取一次设置并且在返回屏幕或重新加载它之前不关心更改,那么也许您可以在调用方法 getSettings 时简单地使用一个可观察对象。类似于:

fun getSettings(callback: SettingsCallback) {
    restClient.getSettings()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({ callback.onFetchedSettings(it) })
}
  1. On getSettings method, should I use the callback or just return the settingsSubject value?

我想说这真的取决于您想如何做事。我更喜欢总是 return 一个 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 一旦有人订阅,最后发出的项目将再次发出,所以这应该仍然有效。

同样,回调没有任何问题。我只是个人认为使用这个响应式接口更干净。