基本結構
我們先來看一段最基本的代碼,分析這段代碼在RxJava中是如何?的。
Observable.OnSubscribe<String> onSubscriber1 = new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("1"); subscriber.onCompleted(); }};Subscriber<String> subscriber1 = new Subscriber<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { }};Observable.create(onSubscriber1) .subscribe(subscriber1);
首先我們來看一下Observable.create的代碼
public final static <T> Observable<T> create(OnSubscribe<T> f) { return new Observable<T>(hook.onCreate(f));}protected Observable(OnSubscribe<T> f) { this.onSubscribe = f;}
直接就是調用了Observable的建構函式來建立一個新的Observable對象,這個對象我們暫時標記為observable1,以便後面追溯。
同時,會將我們傳入的OnSubscribe對象onSubscribe1儲存在observable1的onSubscribe屬性中,這個屬性在後面的上下文中很重要,大家留心一下。
接下來我們來看看subscribe方法。
public final Subscription subscribe(Subscriber<? super T> subscriber) { return Observable.subscribe(subscriber, this);}private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) { ... subscriber.onStart(); hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber); return hook.onSubscribeReturn(subscriber);}
可以看到,subscribe之後,就直接調用了observable1.onSubscribe.call方法,也就是我們代碼中的onSubscribe1對象的call方法
,傳入的參數就是我們代碼中定義的subscriber1對象。call方法中所做的事情就是調用傳入的subscriber1對象的onNext和onComplete方法。
這樣就實現了觀察者和被觀察者之間的通訊,是不是很簡單?
public void call(Subscriber<? super String> subscriber) { subscriber.onNext("1"); subscriber.onCompleted();}
RxJava使用情境小結
1.取資料先檢查緩衝的情境
取資料,首先檢查記憶體是否有緩衝
然後檢查檔案快取中是否有
最後才從網路中取
前面任何一個條件滿足,就不會執行後面的
final Observable<String> memory = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { if (memoryCache != null) { subscriber.onNext(memoryCache); } else { subscriber.onCompleted(); } }});Observable<String> disk = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { String cachePref = rxPreferences.getString("cache").get(); if (!TextUtils.isEmpty(cachePref)) { subscriber.onNext(cachePref); } else { subscriber.onCompleted(); } }});Observable<String> network = Observable.just("network");//主要就是靠concat operator來實現Observable.concat(memory, disk, network).first().subscribeOn(Schedulers.newThread()).subscribe(s -> { memoryCache = "memory"; System.out.println("--------------subscribe: " + s);});
2.介面需要等到多個介面並發取完資料,再更新
//拼接兩個Observable的輸出,不保證順序,按照事件產生的順序發送給訂閱者private void testMerge() { Observable<String> observable1 = DemoUtils.createObservable1().subscribeOn(Schedulers.newThread()); Observable<String> observable2 = DemoUtils.createObservable2().subscribeOn(Schedulers.newThread()); Observable.merge(observable1, observable2) .subscribeOn(Schedulers.newThread()) .subscribe(System.out::println);}
3.一個介面的請求依賴另一個API請求返回的資料
舉個例子,我們經常在需要登陸之後,根據拿到的token去擷取訊息列表。
這裡用RxJava主要解決嵌套回調的問題,有一個專有名詞叫Callback hell
NetworkService.getToken("username", "password") .flatMap(s -> NetworkService.getMessage(s)) .subscribe(s -> { System.out.println("message: " + s); });
4.介面按鈕需要防止連續點擊的情況
RxView.clicks(findViewById(R.id.btn_throttle)) .throttleFirst(1, TimeUnit.SECONDS) .subscribe(aVoid -> { System.out.println("click"); });
5.響應式的介面
比如勾選了某個checkbox,自動更新對應的preference
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);RxSharedPreferences rxPreferences = RxSharedPreferences.create(preferences);Preference<Boolean> checked = rxPreferences.getBoolean("checked", true);CheckBox checkBox = (CheckBox) findViewById(R.id.cb_test);RxCompoundButton.checkedChanges(checkBox) .subscribe(checked.asAction());
6.複雜的資料變換
Observable.just("1", "2", "2", "3", "4", "5") .map(Integer::parseInt) .filter(s -> s > 1) .distinct() .take(3) .reduce((integer, integer2) -> integer.intValue() + integer2.intValue()) .subscribe(System.out::println);//9