Tim
Tim

Reputation: 707

Android Single observer with multiple subscribers in separate classes

ok, so i'm trying to implement rxJava2 with retrofit2. The goal is to make a call only once and broadcast the results to different classes. For exmaple: I have a list of geofences in my backend. I need that list in my MapFragment to dispaly them on the map, but I also need that data to set the pendingIntent service for the actual trigger.

I tried following this awnser, but I get all sorts of errors: Single Observable with Multiple Subscribers

The current situation is as follow:

GeofenceRetrofitEndpoint:

public interface GeofenceEndpoint {
    @GET("geofences")
    Observable<List<Point>> getGeofenceAreas();
}

GeofenceDAO:

public class GeofenceDao {
    @Inject
    Retrofit retrofit;
    private final GeofenceEndpoint geofenceEndpoint;

    public GeofenceDao(){
        InjectHelper.getRootComponent().inject(this);
        geofenceEndpoint = retrofit.create(GeofenceEndpoint.class);
    }

    public Observable<List<Point>> loadGeofences() {
        return geofenceEndpoint.getGeofenceAreas().subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .share();
    }
}

MapFragment / any other class where I need the results

private void getGeofences() {
    new GeofenceDao().loadGeofences().subscribe(this::handleGeoResponse, this::handleGeoError);
}

private void handleGeoResponse(List<Point> points) {
    // handle response
}

private void handleGeoError(Throwable error) {
    // handle error
}

What am I doing wrong, because when I call new GeofenceDao().loadGeofences().subscribe(this::handleGeoResponse, this::handleGeoError); it's doing a separate call each time. Thx

Upvotes: 1

Views: 931

Answers (2)

Than
Than

Reputation: 2769

Maybe it's not answering your question directly, however I'd like to suggest you a little different approach:

Create a BehaviourSubject in your GeofenceDao and subscribe your retrofit request to this subject. This subject will act as a bridge between your clients and api, by doing this you will achieve:

  1. Response cache - handy for screen rotations
  2. Replaying response for every interested observer
  3. Subscription between clients and subject doesn't rely on subscription between subject and API so you can break one without breaking another

Upvotes: 0

tynn
tynn

Reputation: 39843

new GeofenceDao().loadGeofences() returns two different instances of the Observable. share() only applies to the instance, not the the method. If you want to actually share the observable, you'd have to subscribe to the same instance. You could share the it with a (static) member loadGeofences.

private void getGeofences() {
    if (loadGeofences == null) {
        loadGeofences = new GeofenceDao().loadGeofences();
    }
    loadGeofences.subscribe(this::handleGeoResponse, this::handleGeoError);
}

But be careful not to leak the Obserable.

Upvotes: 1

Related Questions