Berlangganan dan Berhenti Berlangganan pada Setiap Item yang Dipancarkan

Saya menggunakan lib reactive-location.

Kasus penggunaan saya adalah saya memiliki aliran objek yang dipancarkan dari sesuatu yang dapat diamati. Barang-barang ini berpotensi dikeluarkan setiap beberapa jam. Segera setelah suatu item dipancarkan, saya ingin mendapatkan lokasi dan menggunakan zipWith(sejauh yang saya mengerti) memancarkan objek yang berisi lokasi tersebut.

Masalahnya adalah: karena objek hanya akan dipancarkan setiap beberapa jam sekali, saya tidak dapat menjaga lokasi tetap panas karena akan menguras baterai.

Jadi saya memerlukan yang berikut: setelah suatu objek dimasukkan ke dalam aliran, berlangganan ke lokasi yang dapat diamati setelah lokasi diperoleh, berhenti berlangganan ke lokasi yang dapat diamati. Hal ini harus dilakukan secara terus menerus.

Sejauh yang saya pahami trafo ini menangani berhenti berlangganan

public <T> Observable.Transformer<T, T> takeNextAndUnsubscribe() {
    return new Observable.Transformer<T, T>() {

        @Override
        public Observable<T> call(Observable<T> tObservable) {
            final BehaviorSubject subject = BehaviorSubject.create();
            Observable source = tObservable.doOnNext(new Action1<T>() {
                @Override
                public void call(T t) {
                    subject.onNext(t);
                }
            });
            return Observable
                    .merge(source.takeUntil(subject), subject)
                    .take(1);
        }

    };
}

Namun bagaimana saya bisa berlangganan lagi setelah objek baru dikirimkan?


person jiduvah    schedule 22.10.2015    source sumber


Jawaban (1)


Sepertinya yang Anda perlukan adalah menggabungkan item sumber dengan lokasi saat ini ketika item tersebut dipancarkan. Tidak perlu sesuatu yang mewah di sini. Cukup gunakan flatMap() pada setiap item sumber untuk menggabungkannya dengan lokasi.

source.flatMap(item ->
        locationProvider
                .getLastKnownLocation()
                .map(location -> new ItemWithLocation<>(item, location))
);

class ItemWithLocation<T> {
    private final T item;
    private final Location location;

    public ItemWithLocation(T item, Location location) {
        this.item = item;
        this.location = location;
    }

    public T getItem() {
        return item;
    }

    public Location getLocation() {
        return location;
    }
}

EDIT: Diperbarui dengan contoh kedua. Yang berikut ini akan berlangganan pembaruan lokasi hingga akurasi tertentu tercapai dan kemudian menggabungkannya dengan item sumber Anda. Kuncinya di sini adalah penggunaan first(). Menggunakannya akan berhenti berlangganan dari penyedia lokasi setiap kali Anda mendapatkan lokasi yang memenuhi kebutuhan Anda.

LocationRequest request = 
        LocationRequest
            .create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(100);

source.flatMap(item ->
        locationProvider
                .getUpdatedLocation(request)
                .first(location -> location.getAccuracy() < 5.0f)
                .map(location -> new ItemWithLocation<>(item, location))
);
person kjones    schedule 23.10.2015
comment
Masalahnya adalah saya ingin lokasi baru, bukan lokasi terakhir yang diketahui - person jiduvah; 23.10.2015
comment
API apa yang Anda gunakan dari lokasi reaktif? Itu tidak jelas jadi saya menggunakan getLastKnownLocation() dalam contoh saya. Saya telah memperbarui jawabannya dengan contoh kedua yang menunjukkan cara menangani berhenti berlangganan dari lokasi yang tidak dapat dihentikan. - person kjones; 23.10.2015