Pergunta

I'm trying to use Rx-Java to create a class for location tracking on Android. What I can't still figure out is how to handle lifecycle of my Observable properly. What I want to have is an Observable that starts tracking location when first subscription happens, and stops location tracking when last subscription is discarded. What I achieved so far is this:

public class LocationObservable 
    implements GooglePlayServicesClient.ConnectionCallbacks, 
               GooglePlayServicesClient.OnConnectionFailedListener, 
               LocationListener {

    private LocationClient locationClient;
    private final PublishSubject<Location> latestLocation = 
        PublishSubject.create();
    public final Observable<Location> locationObservable = 
        Observable.defer(() -> {
        if(!locationClient.isConnected() && !locationClient.isConnecting()) {
            locationClient.connect();
        }
        return latestLocation.asObservable().scan((prev, curr) -> {
            if (Math.abs(prev.getLatitude() - curr.getLatitude()) > 0.000001 ||
                Math.abs(prev.getLongitude() - curr.getLongitude()) > 0.000001)
                return curr;
            else
                return prev;
        }).distinctUntilChanged();});

    public LocationObservable(Context context) {

        locationClient = new LocationClient(context, this, this);
    }

    @Override
    public void onConnected(Bundle bundle) {
        latestLocation.onNext(locationClient.getLastLocation());
    }

    @Override
    public void onDisconnected() {
        latestLocation.onCompleted();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        latestLocation.onError(new Exception(connectionResult.toString()));
    }

    @Override
    public void onLocationChanged(Location location) {
        latestLocation.onNext(location);
    }
}

As you can see, I use Observable#defer to init location callbacks when first client subscribes. I don't know if it's a good approach, but it's the best I came up with at the moment. What I'm still missing is how to stop the location updates when last client of my class unsubscribes from my observable. Or maybe it's something non-idiomatic in Rx, since it's not obvious?

I believe, this use case should be rather standard, and therefore there should be a standard/idiomatic solution for it. Would be happy to know it.

Foi útil?

Solução

private LocationClient locationClient;
private final Observable<Integer> locationObservable = Observable
        .create(new OnSubscribe<Integer>() {

            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                locationClient.connect();
                subscriber.add(Subscriptions.create(new Action0() {

                    @Override
                    public void call() {
                        if (locationClient.isConnected()
                                || locationClient.isConnecting()) {
                            locationClient.disconnect();
                        }
                    }

                }));
            }

        }).multicast(PublishSubject.<Integer> create()).refCount();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top