RxJava 设计理念 观察者模式 Observable lambdas MD
| MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
RxJava 設計理念 觀察者模式 Observable lambdas MD
demo地址
目錄
目錄常用庫
首先寫一個最簡單的觀察者模式
我們再對比下用 rx 寫的觀察者模式
簡化代碼
介紹一個操作符:map
對于 map 的更多用法
對 rx 設計理念的理解
常用庫
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' implementation 'io.reactivex.rxjava2:rxjava:2.x.x'implementation 'com.jakewharton.rxrelay2:rxrelay:2.0.0'implementation "com.github.akarnokd:rxjava2-extensions:0.16.0"implementation "com.squareup.retrofit2:retrofit:2.0.0" implementation "com.squareup.retrofit2:converter-gson:2.0.0" implementation "com.squareup.okhttp3:okhttp:3.7.0" implementation "com.squareup.okhttp3:okhttp-urlconnection:3.0.1" implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'implementation 'top.zibin:Luban:1.1.8' implementation 'com.github.tbruyelle:rxpermissions:0.10.2' implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1' implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'首先寫一個最簡單的觀察者模式
interface Watcher { void update(String str); } interface Watched { void addWatcher(Watcher watcher); void removeWatcher(Watcher watcher); void notifyWatchers(String str); } class ConcreteWatcher implements Watcher { @Override public void update(String str) { Log.i("bqt", "觀察者收到被觀察者的消息:" + str); } } class ConcreteWatched implements Watched { private List<Watcher> list = new ArrayList<>(); @Override public void addWatcher(Watcher watcher) { if (list.contains(watcher)) { Log.i("bqt", "失敗,被觀察者已經注冊過此觀察者"); } else { Log.i("bqt", "成功,被觀察者成功注冊了此觀察者"); list.add(watcher); } } @Override public void removeWatcher(Watcher watcher) { if (list.contains(watcher)) { boolean success = list.remove(watcher); Log.i("bqt", "此觀察者解除注冊觀察者結果:" + (success ? "成功" : "失敗")); } else { Log.i("bqt", "失敗,此觀察者并未注冊到被觀察者"); } } @Override public void notifyWatchers(String str) { for (Watcher watcher : list) { watcher.update(str); } } }演示案例:
private Watcher watcher; private Watched watched; ... watcher = new ConcreteWatcher(); watched = new ConcreteWatched(); ... watched.addWatcher(watcher); watched.notifyWatchers("救命啊"); watched.removeWatcher(watcher);我們再對比下用 rx 寫的觀察者模式
首先,我們創建一個基本的被觀察者Observable:
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> emitter) { emitter.onNext("救命啊-------isDisposed=" + emitter.isDisposed());//false if (new Random().nextBoolean()) emitter.onComplete(); //發送onComplete else emitter.onError(new Throwable("發送onError")); //發送onComplete或onError事件后就取消注冊了 Log.i("bqt", "調用 onComplete 或 onError 后 isDisposed=" + emitter.isDisposed());//true } });接著我們創建Observer來消費這個數據:
Observer<String> observer = new Observer<String>() { @Override public void onSubscribe(Disposable d) { Log.i("bqt", "成功訂閱-------isDisposed=" + d.isDisposed());//false } @Override public void onNext(String s) { Log.i("bqt", "【觀察者接收到了事件】onNext:" + s); } @Override public void onError(Throwable e) { Log.i("bqt", "對Error事件作出響應:" + e.getMessage()); } @Override public void onComplete() { Log.i("bqt", "對Complete事件作出響應"); } };現在我們已經有了Observable和Observer,那么就可以通過subscribe()函數把兩者關聯起來了:
observable.subscribe(observer);//被觀察者注冊觀察者簡化代碼
在以下這個例子中,Observable.just()發送一個消息然后完成,功能類似上面的代碼。
Observable<String> observable = Observable.just("救命啊");接下來,讓我們處理Observer不必要的樣板代碼。如果我們不關心onSubscribe、onCompleted、onError的話,那么可以使用一個更簡單的類來定義onNext()要完成什么功能:
new Consumer<String>() { @Override public void accept(String s) throws Exception { Log.i("bqt", "【觀察者收到被觀察者的消息】onNext:" + s); } };可以用Consumer或Action來定義Observer的每一個部分,Observable.subscribe()函數能夠處理一到四個參數,分別表示onNext(),onError()和onComplete()和onSubscribe函數。
public final Disposable subscribe(Consumer<? super T> onNext) public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete)因此,上述代碼可簡化為:
Observable.just("救命啊").subscribe(new Consumer<String>() { @Override public void accept(String s) throws Exception { Log.i("bqt", "【觀察者收到被觀察者的消息】onNext:" + s); } });使用lambdas表達式去掉丑陋的Consumer代碼:
Observable.just("救命啊") .subscribe(s -> Log.i("bqt", "【觀察者收到被觀察者的消息】onNext:" + s));不僅如此,因為 just 方法可以接受多個不同類型的數據,所以我們可以對一系列數據同時進行處理:
Observable.just("救命啊", 1, true, 1.5f) .subscribe(s -> "【觀察者收到被觀察者的消息】onNext:" + s));介紹一個操作符:map
讓我們來點刺激的。假如我想把我的簽名拼接到"Hello, world!"的輸出中,一個可行的辦法是改變Observable:
Observable.just("Hello, world! -包青天").subscribe(s -> System.out.println(s));這么做存在兩個問題:
- 當你有權限控制Observable時這么做是可行的,但不能保證每次都可以這樣,因為如果你使用的是別人的函數庫呢?
- 如果項目中在多個地方使用此Observable,但只在某一個地方需要增加簽名,這時怎么辦?
你可能會想到,我們可以單獨修改此Subscriber:
Observable.just("Hello, world!") .subscribe(s -> System.out.println(s + " -包青天"));用這個解決方案的話,雖然上面的問題解決了,但同樣也存在一個重要的問題:
因為我希望Subscribers應盡可能的輕量級,而不要耦合任何的業務邏輯(比如對Observable發送的數據做再處理)。
從更概念化的層面上講,Subscribers只是用于被動響應的,而不是主動發送或處理消息的。
接下來我們將介紹如何解決消息轉換的難題:使用Operators。
Operators在消息發送者Observable(被觀察者)和消息消費者Subscriber(觀察者)之間起到操縱消息的作用。RxJava擁有大量的opetators,map()這個operator可以用來將已被發送的消息轉換成另外一種形式:
使用lambdas表達式后:
Observable.just("Hello, world!") .map(s -> s + " -包青天") .subscribe(s -> System.out.println(s));很酷吧?這里的map()操作符本質上是一個用于轉換消息對象的Observable。我們可以級聯調用任意多個的map()函數,一層一層地將初始消息轉換成Subscriber需要的數據形式。
對于 map 的更多用法
map()函數有趣的一點是:它不需要發送和原始的Observable一樣的數據類型。
假如我的Subscriber不想直接輸出原始的數據,而是想輸出原始數據的hash值,可以這樣寫:
這樣,我們的原始輸入是字符串,但Subscriber最終收到的是Integer類型。
正如說過的,我們希望Subscriber做盡量少的工作,所以我們還可以把hash值轉換成字符串的操作移動到一個新的map()函數中:
Observable.just("Hello, world!") .map(s -> s.hashCode()) .map(i -> Integer.toString(i)) .subscribe(s -> System.out.println(s));給力吧!我們的Observable和Subscriber完全還是原來的代碼,我們只是根據不同的需求在中間添加了一些變換的操作。
類似的案例:
Observable.just(System.currentTimeMillis()) .map(time -> time + 1000 * 60 * 60)//改變時間的值 .map(time -> new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(new Date(time))) .subscribe(string -> Log.i("bqt", string));對 rx 設計理念的理解
上面只是一個簡單的例子,但其中有幾個思想你需要理解:
第一:通過上面的Observable和Subscriber,你能完成任何你想做的事情,也就是說這是一個可以處理任何事情的通用的框架。
- 你的Observable可以是一個數據庫查詢,Subscriber獲得查詢結果然后將其顯示在屏幕上。
- 你的Observable可以是屏幕上的一個點擊,Subscriber響應該事件。
- 你的Observable可以從網絡上讀取一個字節流,Subscriber將其寫入本地磁盤中。
第二:Observable和Subscriber與它們之間的一系列轉換步驟是相互獨立的。
- 我們可以在消息發送者Observable和消息消費者Subscriber之間加入任意個你想要的map()函數,這個系統是高度可組合的,它很容易對數據進行操縱。
- 只要operators符合輸入輸出的數據類型,那么我可以得到一個無窮盡的調用鏈。
結合這兩個概念,你可以看到一個有極大潛能的系統。并且我們還只是介紹了RxJava中的其中一個operator,實際上RxJava中還定義了大量的其他的operators,在你深入了解后,你會深深感嘆:臥槽,你牛逼。
2018-9-18
轉載于:https://www.cnblogs.com/baiqiantao/p/463e135c55afb336e7d199ee7a9658bd.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的RxJava 设计理念 观察者模式 Observable lambdas MD的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FreeBSD长模式不兼容
- 下一篇: CSS实现树形结构 + js加载数据