SORU
19 ŞUBAT 2014, ÇARŞAMBA


Basit Android Geri arama ne zaman bir RxJava Gözlemlenebilir kullanmak gerekir?

Benim app için ağ üzerinde çalışıyorum. Denemek için Desided Meydanı Retrofit. Basit Callback destek verdiklerini görüyorum

@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);

ve RxJava Observable

@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);

Her ikisi de ilk bakışta oldukça benzer. Ama uygulamaya gelince ilginç oluyor

Basit bir geri arama uygulaması ile bu gibi görünecektir:

api.getUserPhoto(photoId, new Callback<Photo>() {
    @Override
    public void onSuccess() {
    }
});

oldukça basit ve anlaşılır. Ve Observable ile hızlı bir şekilde ayrıntılı ve oldukça karmaşık bir hal alır.

public Observable<Photo> getUserPhoto(final int photoId) {
    return Observable.create(new Observable.OnSubscribeFunc<Photo>() {
        @Override
        public Subscription onSubscribe(Observer<? super Photo> observer) {
            try {
                observer.onNext(api.getUserPhoto(photoId));
                observer.onCompleted();
            } catch (Exception e) {
                observer.onError(e);
            }

            return Subscriptions.empty();
        }
    }).subscribeOn(Schedulers.threadPoolForIO());
}

Sadece bu kadar da değil. Hala böyle bir şeyi yapmak zorunda:

Observable.from(photoIdArray)
        .mapMany(new Func1<String, Observable<Photo>>() {
            @Override
            public Observable<Photo> call(Integer s) {
                return getUserPhoto(s);
            }
        })
        .subscribeOn(Schedulers.threadPoolForIO())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Photo>() {
            @Override
            public void call(Photo photo) {
                //save photo?
            }
        });

Bir şey mi kaçırıyorum? Ya bu yanlış bir durum Observables kullanmak için mi? /Observable basit Geri arama sona mı tercih edersin?

Güncelleme

Güçlendirme kullanarak Jake Wharton örnek U2020 projede onun cevabı ya @Niels gösterdiği gibi yukarıda örnek olmaktan çok daha kolaydır. Ama esas soru hala aynı - zaman öyle ya da böyle kullanabilir mi? kalır

CEVAP
28 NİSAN 2015, Salı


Basit ağ şeyler için, Geri arama üzerinde RxJava avantajları çok sınırlıdır. Basit getUserPhoto örnek:

RxJava:

api.getUserPhoto(photoId)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Photo>() {
         @Override
            public void call(Photo photo) {
            }
     });

Geri arama:

api.getUserPhoto(photoId, new Callback<Photo>() {
    @Override
    public void onSuccess(Photo photo, Response response) {
    }
});

RxJava varyant Geri versiyonu daha çok daha iyi değildir. Şimdi, diyelim ki hata-işlem görmezden. Bu Fotoğraf: bir liste yapalım

RxJava:

api.getUserPhotos(userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(new Func1<List<Photo>, Observable<Photo>>() {
    @Override
    public Observable<Photo> call(List<Photo> photos) {
         return Observable.from(photos);
    }
})
.filter(new Func1<Photo, Boolean>() {
    @Override
    public Boolean call(Photo photo) {
         return photo.isPNG();
    }
})
.subscribe(
    new Action1<Photo>() {
    @Override
        public void call(Photo photo) {
            list.add(photo)
        }
    });

Geri arama:

api.getUserPhotos(userId, new Callback<List<Photo>>() {
    @Override
    public void onSuccess(List<Photo> photos, Response response) {
        List<Photo> filteredPhotos = new ArrayList<Photo>();
        for(Photo photo: photos) {
            if(photo.isPNG()) {
                filteredList.add(photo);
            }
        }
    }
});

Şimdi, RxJava varyant hala Lambda ile Geri varyant için alıcı daha yakın olması olurdu. küçük olsa da, değil. Eğer JSON yem erişiminiz varsa ayrıca, bu türden PNG var görüntüleme yaparken tüm fotoğrafları almak için garip olurdu. Sadece görüntüler PNG için yem ayarlayın.

İlk sonuç

Doğru formatta olması için hazırlanmış basit bir JSON yüklerken kod temeli daha küçük yapmaz.

Şimdi işler biraz daha ilginç hale getirmek. Hadi sadece userPhoto almak istiyorum ama İnstagram-clone var ki, ve 2 JSON ... ... almak istediğiniz: 1. ()getUserDetails 2. () getUserPhotos

Buna paralel olarak bu iki JSON yüklemek istediğiniz, ve her ikisi de yüklü olduğunda, sayfa görüntülenemiyor. Geri arama varyantı biraz daha zor olacak: 2 geri, etkinlik veri depolama, ve eğer tüm verileri yüklendi, sayfa ekran: oluşturmak zorunda

Geri arama:

api.getUserDetails(userId, new Callback<UserDetails>() {
    @Override
    public void onSuccess(UserDetails details, Response response) {
        this.details = details;
        if(this.photos != null) {
            displayPage();
        }
    }
});

api.getUserPhotos(userId, new Callback<List<Photo>>() {
    @Override
    public void onSuccess(List<Photo> photos, Response response) {
        this.photos = photos;
        if(this.details != null) {
            displayPage();
        }
    }
});

RxJava:

private class Combined {
    UserDetails details;
    List<Photo> photos;
}


Observable.zip(api.getUserDetails(userId), api.getUserPhotos(userId), new Func2<UserDetails, List<Photo>, Combined>() {
            @Override
            public Combined call(UserDetails details, List<Photo> photos) {
                Combined r = new Combined();
                r.details = details;
                r.photos = photos;
                return r;
            }
        }).subscribe(new Action1<Combined>() {
            @Override
            public void call(Combined combined) {
            }
        });

Bir yerlere geliyoruz! RxJava kodu şimdi geri arama seçeneği gibi büyük. RxJava kodu daha sağlamdır; Eğer yüklenecek üçüncü bir JSON (en yeni Videolar) lazım olduğunda ne olacağını düşündün mü? Bu RxJava Geri varyant birden fazla yerde ayarlanması (her bir geri arama eğer tüm veri alınır diye kontrol etmemiz lazım) ihtiyacı olsa da sadece küçük bir ayar gerekiyor.

Başka bir örnek; veri Güçlendirme kullanarak yükler otomatik tamamlama bir alan yaratmak istiyoruz. Her zaman bir EditText bir TextChangedEvent bir webcall yapmak istemiyoruz. Hızlı yazarken, sadece son öğe aramak için geçerli bir neden gerekir. RxJava üzerinde debounce operatörü kullanabilirsiniz:

inputObservable.debounce(1, TimeUnit.SECONDS).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                // use Retrofit to create autocompletedata
            }
        });

Geri arama türevi yaratmak istemiyorum ama bu çok daha fazla iş olduğunu anlayacaksınız.

Sonuç: RxJava veri akışı olarak gönderilen son derece iyi. Güçlendirme Gözlemlenebilir aynı zamanda akış tüm öğeleri iter. Bu Geri arama için kendisini karşılaştırıldığında özellikle yararlı değil. Ama birden fazla eleman akışı ve farklı zamanlarda itti ve zamanlama ile ilgili bir şeyler yapmak gerektiğinde, RxJva kod çok daha rahat yapar.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • DJPixcell

    DJPixcell

    20 NİSAN 2007
  • L- Crysis

    L- Crysis

    30 Aralık 2011
  • Madeon

    Madeon

    31 Ocak 2010