dev.farmer
dev.farmer

Reputation: 2819

RxJava, Is it correct to clear disposable in subscribe?

Usually, I call "disposable.clear()" on "onStop/onDestroy" function.

But today, I saw that my co-worker using the below code that calling the clear function in the subscribe function like:

val disposable: CompositeDisposable = CompositeDisposable()

...

disposable.add(
    MyObservable()
        .subscribeOn(ioScheduler)
        .observeOn(uiScheduler)
        .subscribe {

            // doSomething...

            disposable.clear // My question is here.
        }
)

Actually, it looks like working fine. But I don't know this code is correct or not...

Upvotes: 3

Views: 8234

Answers (2)

Andrei Tanana
Andrei Tanana

Reputation: 8442

Note that in case of your co-worker only first value from MyObservable will be handled. It can be the point but also it can be an error.

Upvotes: 0

Leo
Leo

Reputation: 14860

When using RxJava in Android I normally "dispose" all disposables in onDestroy. It is safe enough to dispose of them in onDestroy because even if onDestroy never gets called you can safely assume that the system has killed your application process or the component that subscribed to the Observable.

The reason I never dispose a subscription in onSuccess or onNext is because for example, in the case of a Flowable...onNext can be emitted multiple times and it wouldn't make sense to dispose the subscription.

In fact, what I normally do is wrap the CompositeDisposable inside a LifecycleObserver so that it can be garbage-collected automatically based on a life cycle aware component. Here's an implementation that I use a lot...

class AutoDisposable : LifecycleObserver{

    lateinit var compositeDisposables: CompositeDisposable

    /**
     * Binds this observer to the specified life cycle object
     *
     * @param lifecycle The lifecycle object to bind to
     */
    fun bindTo(lifecycle: Lifecycle){
        lifecycle.addObserver(this)
        compositeDisposables = CompositeDisposable()
    }

    /**
     * Registers a disposable that will be disposed when the bound lifecycle object is destroyed
     *
     * @param disposable The disposable to register
     */
    fun addDisposable(disposable: Disposable){

        if(::compositeDisposables.isInitialized){
            compositeDisposables.add(disposable)
        }
        else{
            throw Exception("This object must be bound to a lifecycle before registering a disposable")
        }
    }

    /**
     * Disposes all registered disposables
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy(){
        compositeDisposables.dispose()
    }

}

Then on an activity (or fragment) all you have to do is...

class MyActivity : AppCompatActivity(){

    private val autoDisposables: AutoDisposable =
        AutoDisposable()

    override fun onCreate(savedInstanceState: Bundle?) {
        autoDisposables.bindTo(lifecycle)
    }

    override fun onStart(){
        autoDisposables.add(
             MyObservable()
             .subscribeOn(ioScheduler)
             .observeOn(uiScheduler)
             .subscribe {

                 // handle onNext
             }
        )
    }
}

Then you don't need to worry about, clearing or disposing your subscriptions. You can even go one step further and create a base activity or fragment that takes care of binding the CompositeDisposable and expose protected function to add disposables...

//on a base activity
protected fun registerDisposable(disposable: Disposable){
     autoDisposables.addDisposable(disposable)
}

Upvotes: 7

Related Questions