1

I've just learned rxjava, rxkotlin, dagger and retrofit, but I don't know the approach to take when communicating with server/db and how to store information locally. There are 3 questions at the end. Please help

@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. 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)
  2. 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)
  3. On getSettings method, should I use the callback or just return the settingsSubject value?
4

1 回答 1

0
  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)

Yes absolutely (It's not done automatically). Specially if your subscribers try to access some object that might no longer be there such as views when you send the app to the background. Although there's nothing wrong with your approach, Rx already has a CompositeDisposable that does exactly what you're doing. You can use CompositeDisposable.add(Disposable) to add disposables and then CompositeDisposable.clear() to dispose all the disposables. You also have CompositeDisposable.dispose(), but this renders the composite disposable unusable afterwards and might not be what you want.

  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)

Hard to say without the whole picture. What you have here looks like a database that can be observed for any change. I mean, looks like every time there's a change in the settings you could post something in the subject and trigger all its subscribers. If this is what you want then that seems ok. If you want to read the settings once and not care about changes until you come back to the screen or reload it, then maybe you could simply use an observable whenever you call the method getSettings. Something like:

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?

I would say this really depends on how you want to do things. I prefer to always return an observable and let the calling code decide what to do:

fun getSettings() =
    restClient.getSettings()
        .subscribeOn(Schedulers.io())

// In the calling code for example
interactor.getSettings()
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(/* use value */)

In your case if you want to keep the subject, you can still do it:

fun getSettings() = settingsSubject.subscribeOn(Schedulers.io())

// In calling code for example
interactor.getSettings()
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(/* use value */)

because you're using a BehaviorSubject the last emitted item will be emitted again once anyone subscribes, so this should still work.

Again, there's nothing wrong with the callback. I just personally think that it's cleaner to use this reactive interface.

于 2018-03-07T22:29:46.453 回答