4

Rx-Java を使用して、Android での位置追跡用のクラスを作成しようとしています。私がまだ理解できないのは、Observable のライフサイクルを適切に処理する方法です。私が欲しいのは、最初のサブスクリプションが発生したときに位置の追跡を開始し、最後のサブスクリプションが破棄されたときに位置の追跡を停止する Observable です。これまでに達成したことは次のとおりです。

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);
    }
}

ご覧のとおりObservable#defer、最初のクライアントがサブスクライブするときにロケーション コールバックを開始するために使用します。良いアプローチかどうかはわかりませんが、現時点で思いついたのはこれが最善です。私がまだ欠けているのは、クラスの最後のクライアントがオブザーバブルからサブスクライブを解除したときに位置情報の更新を停止する方法です。それとも、明らかではないため、Rxでは慣用的ではないものでしょうか?

私は、このユースケースはどちらかというと標準的なものであるべきだと考えています。したがって、標準的/慣用的なソリューションが必要です。知っていただければ幸いです。

4

1 に答える 1

5
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();
于 2014-03-04T06:32:36.320 に答える