3

since i would like to start my new app with a clean base im looking for a good way sharing Informations around different classes. For an example i would like to subscribe to an interface which may be used/shared by different classes.

Example for the interface/Observable way:

class SingleTonHolder {
    private static _instance = null;  // and initalize it using a static method.
    private List<MyListener> myListeners new ArrayList<>();
    public SingleTonHolder getInstance(){ return _instance }

    public void registerListener(MyListener listener) { myListeners.add(listener); }
    public void removeListener(MyListener listener) { myListeners.remove(listener); }

    public void doSomethingToTheListener(...) { for(MyListener l : myListeners) l.doSomethingToTheListener(..); }
}

ClassOne extends MyListener {
  public void onCreate() { 
      SingleTonHolder.getInstance().registerListener(this); 
  }
  public vond onDestroy() { 
      SingleTonHolder.getInstance().removeListener(this); 
  }
}

and another class to listen for changes.

ClassTwo {
  MyListener listener = null;
  public void onCreate() { 
      listener = new MyListener( () => { .... });
      SingleTonHolder.getInstance().registerListener(listener); 
  }
  public vond onDestroy() { 
      SingleTonHolder.getInstance().removeListener(listener); 
  }
}

This does work and looks like the default solution. Everytime another Object calls SingleTonHolder.doSomethingToTheListener() it notify all registered listeners for changes.

Since i would like to try the same solution using RxJava2 and RxAndroid2 which lacks documentation i have tried the following way doing it.

Class CallFactory{
    public Obvservable<List<Data>> getDummyData() { return anDummyObservable; }
}

Then ive created a Singleton Class which has a function to modify/observ onec a client subscribes.

public Observable<List<Data>> getData() {
    return CallFactory.with(context)
           .getDummyData(...)
           .map(modifyList -> { /** do some processing **/return modifyList;          
    }) 
}

which doesnt work as excepted since every time a client subscribes it "recall" it and the client keeps connected until onCompleted() is called.

My first try to share the informations to all subscribed clients ive created a PublishSubject in my Singleton Class.

private PublishSubject<List<Data>> sharedSubject = PublishSubject.create(); 

Now i let my clients subscribe to the subjects using a method like

public PublishSubject getSharedSubject() { return this.sharedSubject; }

If i would like to send a Message which should be received by all listening clients then i have created something like

public void setNewData(List<Data> data) {
    sharedSubject.onNext(data);
}

I am pretty sure that is not the way it should be, but is rxjava designed to serve such a solution? If i want to share events different then onNext, onError, onComplete, do i need to wrap an Interface in the onNext?

The codes are not tested and just to show how i understood it. Any help would be appreciate.

Emanuel
  • 8,027
  • 2
  • 37
  • 56

1 Answers1

2

Yes, RxJava used those 3 basic abstract callbacks onNext<T> onComplete() and onError().

But the important part that I believe you've missed is that, the Observer and Consumer are generic abstractions of an interface. Meaning you'll only have 3 callbacks, but you'll have 3 callbacks PER DATA TYPE.

The main idea on RxJava is to create the streams of data. Meaning you would have a PublishSubject<List<Data>>, a PublishSubject<Foo>, a PublishSubject<Bar>, etc, etc. And then use one of the two interfaces Observer<T> or Consumer<T>. There's no need to create another interface or wrap it in something else. Just use the ones supplied by RxJava and put all the information you need inside the data.

I hope it helps.

Example:

// first class
public static class Foo implements Consumer<Data> {
   Disposable d; 
   public Foo() {
      this.d = SingleTonClass.subject.subscribe(this);
   }

   @Override void accept(Data data) {
         .. here the original data
   }

}

// second class
public static class Bar implements Consumer<MappedData> {
   Disposable d; 
   public Foo() {
      this.d = SingleTonClass.subject
          .map( some data transform  )
          .subscribe(this);
   }

   @Override void accept(MappedData data) {
         .. here the data after the map
   }


}



class SingleTonClass {
    public static PublishSubject<Data> subject = PublishSubject.create();

  // then feel free to fire events in the subject:
    public static void onSomethingHappen(){
      subject.onNext(new Data(1));
    }

    public static void onOtherThingHappen(){
      subject.onNext(new Data(2));
    }
}

all in all, I wouldn't wrap the Rx calls into other things, but simply use them directly where needed.

Emanuel
  • 8,027
  • 2
  • 37
  • 56
Budius
  • 39,391
  • 16
  • 102
  • 144
  • Thank you. This was just an example ;-) I know that it is used to add new Data to a stream and inform the subscribers and of course call onComplete() when all data has been received. Since the Observer or Consumer is generic i may fill it with any data i would like to (even an interface(!)). But this is not the goal since i would like to share the Data around different Classes. Since PublishSubject is used (doc) as Observer and Observable this looks promising. Did i get something wrong? ;-) – Emanuel Feb 20 '17 at 21:14
  • so each class that wants to receive the data will `implement Consumer>` and all of them can observer the PublishSubject – Budius Feb 20 '17 at 21:16
  • Sounds great, thank you. May you provide a sample and edit your answer? Thank you so far. – Emanuel Feb 20 '17 at 21:16
  • Its very hard to understand RXJava (2) since the documentation is very hard to read (https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0). Jack Whartons presentation (https://www.youtube.com/watch?v=htIXKI5gOQU) didnt help aswell. So an example would be great! Thank you for your effort! – Emanuel Feb 20 '17 at 21:18
  • I'm also midway through my big project that is deeply using RxJava2 and I'm really enjoying it, but it really takes a different way of thinking your code to be just connecting Observables and Observers. I've added some example, I hope it helps. – Budius Feb 20 '17 at 21:26
  • Thank you. It helps me alot. Do i need to unsubscribe in onPause/onDestroy and resubscribe when onResume or does RXAndroid handle it byitself? – Emanuel Feb 20 '17 at 21:26
  • Nothing is automatic and u 100% have to dispose it or else you'll get memory leaks. Check my edit, I've added the `Disposable` in the classes. You have to dispose them on the appropriate places. I know there's some stuff on RxAndroid to link with the life-cycle, but I've never used, so I can't say for sure. – Budius Feb 20 '17 at 21:29