0

Is it acceptable to create Rx Observables in custom Application subclass. Reason for doing is, I can create BehaviorSubject inside the Application and will ask for changes every 10 minutes from Server, every Activity or Fragment which subscribes to this Observable will get only last state of changes.

Question is whether this architecture could be considered safe in terms of application lifecycle handling and easy to use?

class CustomApplication extends Application {
   ...

   BehaviorSubject<Friends> mFriends = new BehaviorSubject<Friends>;
   public void createObservables() {
      Observable.create(new Observable.OnSubscribe<Friends>() {
         public void call(Subscriber<?> s) {
            while(true) {
               mFriends.onNext("randomFriendN");
               sleep(10sec);
            }
         }
      })
      .subscribeOn(Schedulers.newThread())
      .subscribe(new Observer<List<NewsCategory>>() {
         public void onNext(Friends f) { //empty }
      });
   }
   public BehaviorSubject<Friends> getFriends() {
      return mFriends;
   }
}

UPDATE: Everytime when new activity created and it wants to get data it can get it ApplicationContext's BehaviorSubject then subscribe to it, and Subject will emit last emitted value; Why I want to do like this? E.g. Lets say you have news items, you fetched news feed and you want to start background task which fetches news item full content, in that case I can start fetching data while you are scrolling news list, and when you click detailed activity, we can show it from already fetched, or just download it.

4
  • 1
    Could you perhaps provide some pseudo code to clear up any ambiguity? Commented May 17, 2014 at 12:49
  • provided with kind of pseudo code, thanks for advice Commented May 17, 2014 at 13:03
  • Just a improvement tips: BehaviorSubject is also a Observer. You can subscribe(BehaviorSubject) directly. Commented May 18, 2014 at 9:08
  • To me this is not safe. Even if you unsubscribe everything from the subject, the Observable sending message down the subject would never get garbage collected. If you call createObservables twice, both observables will be around forever (Specially because this is in Application). Commented May 25, 2014 at 14:37

1 Answer 1

2

I think this is perfectly safe as long as createObservables() is only called once during application initialization. A few suggested changes...

I wouldn't expose the BehaviorSubject part of mFriends in the returned value from getFriends(). That way callers of getFriends() will not be tempted to call onNext(). Change it to:

public Observable<Friends> getFriends() {
    return mFriends;
}

If you want to be super safe use .asObservable() and callers will not even be able to cast the return value back to a BehaviorSubject.

public Observable<Friends> getFriends() {
    return mFriends.asObservable();
}

I would also update your createObservable() method to call the BehaviorSubject onNext() from the subscribe callback. Here is your code slightly modified to use NewsItems.

BehaviorSubject<List<NewsItem>> mNewsItemSubject = BehaviorSubject.create();

void createObservables() {
    Observable
            .timer(10, 10, TimeUnit.SECONDS, Schedulers.newThread())
            .flatMap(new Func1<Long, Observable<List<NewsItem>>>() {
                @Override
                public Observable<List<NewsItem>> call(Long aLong) {
                    // Normally you would create a network API that returns Observable<NewsItem>.
                    // For now just pretend this returned Observable makes an Observable
                    // network request.
                    return Observable.just(
                            Arrays.asList(
                                    new NewsItem("fakeNewsItem"),
                                    new NewsItem("fakeNewsItem1")
                            )
                    );
                }
            })
            .subscribe(new Action1<List<NewsItem>>() {
                @Override
                public void call(List<NewsItem> newsItems) {
                    mNewsItemSubject.onNext(newsItems);
                }
            });
}

public Observable<List<NewsItem>> observeNewsItems() {
    return mNewsItemSubject;
}

Your Android Activities can then call ((CustomApplication)getApplication()).observeNewsItems() to get the latest news items and any updates while the Activity is visible.

final Observable<List<NewsItem>> newsItemsObservable = 
    ((CustomApplication) getApplication()).observeNewsItems();

newsItemsObservable
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<List<NewsItem>>() {
            @Override
            public void onCompleted() {
                // All done.
            }

            @Override
            public void onError(Throwable e) {
                // Notify user of error (maybe)
            }

            @Override
            public void onNext(List<NewsItem> newsItems) {
                // Update the UI with newsItems.
            }
        });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.