Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way to handle subscriptions in RxJava/RxAndroid for an Activity Lifecycle?

I am just getting started on RxJava/RxAndroid. I want to avoid context leaks so I created a BaseFragment like so:

public abstract class BaseFragment extends Fragment {

    protected CompositeSubscription compositeSubscription = new CompositeSubscription();

    @Override
    public void onDestroy() {
        super.onDestroy();

        compositeSubscription.unsubscribe();
    } 
} 

And inside my fragment that extends BaseFragment, I am doing this:

protected void fetchNewerObjects(){
        if(!areNewerObjectsFetching()){ //if it is not already fetching newer objects

            Runtime.getRuntime().gc();//clean out memory if possible

            fetchNewObjectsSubscription = Observable
                .just(new Object1())
                .map(new Func1<Object1, Object2>() {
                    @Override
                    public Object2 call(Object1 obj1) {
                        //do bg stuff
                        return obj2;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Object2>() {
                    @Override
                    public void onCompleted() {
                        compositeSubscription.remove(fetchNewObjectsSubscription);
                        fetchNewObjectsSubscription = null;
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(ArrayList<NewsFeedObject> newsFeedObjects) {
                        //do stuff
                    }
                });

        //add subscription to composite subscription so it can be unsubscribed onDestroy()
        compositeSubscription.add(fetchNewObjectsSubscription);
    }
}

protected boolean areNewerObjectsFetching(){
    if(fetchNewObjectsSubscription == null || fetchNewObjectsSubscription.isUnsubscribed()){ //if its either null or is in a finished status
        return false;
    }
    return true;
}

So I guess my question is two-fold:

  1. Will this stop context leaks because I am unsubscribing onDestroy()?

  2. And am I properly keeping track of wether the observable is "running" by setting the subscription to null after completion and checking the nullity?

like image 810
Sree Avatar asked Aug 03 '15 19:08

Sree


People also ask

What is RxJava and RxAndroid?

RxAndroid is a RxJava for Android extension that is only used in Android applications. RxAndroid added the Android-required Main Thread. We will need the Looper and Handler for Main Thread execution in order to work with multithreading in Android. Note: AndroidSchedulers are provided by RxAndroid.

Is RxJava lifecycle aware?

RxJava is not lifecycle aware.

What is RxJava and why to use it?

RxJava is a Java library that enables Functional Reactive Programming in Android development. It raises the level of abstraction around threading in order to simplify the implementation of complex concurrent behavior.

Can I use RxJava with Kotlin?

RxJava can be used even when using the Kotlin language for app development.


1 Answers

  1. Yes, it will stop, but you should also set subscription to null in onError too (or after error, you won't load items again).

    Also do not forget that fragment can be stopped, but not destroyed (in back stack, for example) and you might not want to observe anything in this case. If you move unsubscribe from onDestroy to onStop do not forget to initialise compositeSubscription in onCreateView each time view is created (because after CompositeSubscription is unsubscribed you no longer can add subscriptions there).

  2. Yes correct. But I think that compositeSubscription.remove can be omitted, because you already check for null.

like image 187
marwinXXII Avatar answered Oct 13 '22 14:10

marwinXXII