學習RxJava之前必須先來看下Java的設置模式之一:觀察者模式(Observer Pattern)。
原因:RxJava的都是基於觀察者模式構建的。
關於觀察者模式論述總結:
意圖:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
主要解決:一個對象狀態改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協作。
何時使用:一個對象(目標對象,被觀察者)的狀態發生改變,所有的依賴對象(觀察者對象)都將得到通知,進行廣播通知。
如何解決:使用面向對象技術,可以將這種依賴關係弱化。
關鍵代碼:在抽象類裏有一個 ArrayList 存放觀察者們。
下面給出傳統觀察者模式代碼:
代碼目錄結構很簡單,被觀察者(Observable)和觀察者(Observer)各有一個接口和具體的(Concrete)實現類:
被觀察者接口:
package com.xw.observerpatterndemo.observable;
import com.xw.observerpatterndemo.observer.Observer;
public interface Observable {
/**
* 將觀察者註冊到被觀察者的List集合中
* @param observer
*/
public void registerObserver(Observer observer);
/**
* 將觀察者從被觀察者的List集合中刪除
* @param observer
*/
public void removeObserver(Observer observer);
/**
* 當被觀察者狀態發生改變時通知觀察者進行相應的更新(通過觀察者對象調用觀察者的update()方法)
*/
public void notifyObservers();
}
被觀察者的具體實現類:
package com.xw.observerpatterndemo.observable;
import java.util.ArrayList;
import java.util.List;
import com.xw.observerpatterndemo.observer.Observer;
public class ConcreteObservable implements Observable {
private List<Observer> mObservers;
private int edition;
private float cost;
public ConcreteObservable() {
mObservers = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
mObservers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int i = mObservers.indexOf(observer);
if(i>=0){
mObservers.remove(i);
}
}
@Override
public void notifyObservers() {
for(int i=0 ; i < mObservers.size();i++){
Observer observer = mObservers.get(i);
observer.update(edition,cost);
}
}
public void setInfomation(int edition,float cost){
this.edition = edition;
this.cost =cost;
notifyObservers();
}
}
觀察者(Observer)接口:
package com.xw.observerpatterndemo.observer;
public interface Observer {
/**
* 同步更新觀察者的狀態
* @param edition
* @param cost
*/
public void update(int edition,float cost);
}
觀察者具體實現類(ConcreteObserver):
package com.xw.observerpatterndemo.observer;
import android.util.Log;
public class ConcreteObserver implements Observer {
private int edition;
private float cost;
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(int edition, float cost) {
this.edition = edition;
this.cost = cost;
buy();
}
private void buy() {
Log.v("ConcreteObserver",name+"購買了"+edition+"期雜誌,花了"+cost+"元");
}
}
下面是我用Android studio對上面的類的調用(你可以用eclipse),在MainActivity中:
package com.xw.observerpatterndemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.xw.observerpatterndemo.observable.ConcreteObservable;
import com.xw.observerpatterndemo.observer.ConcreteObserver;
public class MainActivity2 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
//創建被觀察者
ConcreteObservable concreteObservable = new ConcreteObservable();
//創建3個觀察者
ConcreteObserver observerA = new ConcreteObserver("A");
ConcreteObserver observerB = new ConcreteObserver("B");
ConcreteObserver observerC = new ConcreteObserver("C");
concreteObservable.registerObserver(observerA);
concreteObservable.registerObserver(observerB);
concreteObservable.registerObserver(observerC);
//concreteObservable.removeObserver(observerA);
concreteObservable.setInfomation(8,28);
}
}
上面被觀察者代碼中,一旦它的數據狀態發生改變concreteObservable.setInfomation(8,28);上面定義的三個觀察者都會隨着它更新數據狀態,後臺輸出的結果:
2020-06-01 4267-4267/? V/ConcreteObserver: A購買了8期雜誌,花了28.0元
2020-06-01 4267-4267/? V/ConcreteObserver: B購買了8期雜誌,花了28.0元
2020-06-01 4267-4267/? V/ConcreteObserver: C購買了8期雜誌,花了28.0元
熟悉了觀察者模式之後再來看RxJava的定義和使用就比較順其自然了,RxJava的使用通常分爲三步:
(1) 創建Observable:
Observable 的字面意思是被觀察者,使用 Rxjava時需要創建一個被觀察者,它會決定什麼時候觸發事件以及觸發怎樣的事件。有點類似上游發送命令,可以在這裏決定異步操作模塊的順序和異步操作模塊的次數。
(2) 創建 Observer:
Observe :即觀察者,它可以在不同的線程中執行任務。這種模式可以極大地簡化併發操作,因爲它創建了一個處於待命狀態的觀察者哨兵,可以在未來某個時刻響應被觀察者(Observable)的通知,而不需要阻塞等待Observable發射來數據。
(3) 使用 subscribe()進行訂閱,即訂閱關係:
創建了Observable和 observer 之後,我們還需要使用 subscribe()方法將它們連接起來,這樣整個上下游就能銜接起來實現鏈式調用,產生訂閱關係。
上面的三步也進一步說明了RxJava的四要素:
① 被觀察者Observable;② 觀察者Observer; ③ 訂閱關係 subscribe() ;④ 事件;
用一句話概括四者的關係就是:Observable 和 Observer 通過 subscribe() 方法實現訂閱關係,從而 Observable 可以在需要的時候發出事件來通知 Observer。
按照上面的使用三部曲舉一個簡單的例子:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
public class MainActivity extends AppCompatActivity {
private TextView textTips;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textTips = findViewById(R.id.text_tips);
//第一步:創建被觀察者
Observable observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("我愛我的故鄉!");
emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
emitter.onNext("心與心雖遠隔千里!");
emitter.onNext("但與故鄉確咫尺之間!");
emitter.onComplete();
}
});
//第二步:創建觀察者
Observer observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.v("ssss",s);
textTips.setText(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
//第三步:產生訂閱關係:
observable.subscribe(observer);
}
}
運行程序,我還是在Android Studio中運行的,控制檯輸出結果如下:
2020-06-02 23617-23617/? V/ssss: 我愛我的故鄉!
2020-06-02 23617-23617/? V/ssss: 那是我無數個夜晚醒來後魂牽夢縈的地方!
2020-06-02 23617-23617/? V/ssss: 心與心雖遠隔千里!
2020-06-02 23617-23617/? V/ssss: 但與故鄉確咫尺之間!
被觀察者、觀察者、訂閱方法我們都直觀的創建和調用了,那麼什麼是RxJava中所說的事件呢?
上述的例子中,在“第二步:創建觀察者”的對象new Observer<String>() { ...}中,必須實現的四個方法onSubscribe(Disposable d) 、onNext(String s) 、 onError(Throwable e) 、onComplete(),後三者就是RxJava的三個事件:
來看一下它們在Observer接口中的源碼定義:
package io.reactivex;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
public interface Observer<T> {
/**
* Provides the Observer with the means of cancelling (disposing) the
* connection (channel) with the Observable in both
* synchronous (from within {@link #onNext(Object)}) and asynchronous manner.
* @param d the Disposable instance whose {@link Disposable#dispose()} can
* be called anytime to cancel the connection
* @since 2.0
*/
void onSubscribe(@NonNull Disposable d);
/**
* Provides the Observer with a new item to observe.
* <p>
* The {@link Observable} may call this method 0 or more times.
* <p>
* The {@code Observable} will not call this method again after it calls either {@link #onComplete} or
* {@link #onError}.
*
* @param t
* the item emitted by the Observable
*/
void onNext(@NonNull T t);
/**
* Notifies the Observer that the {@link Observable} has experienced an error condition.
* <p>
* If the {@link Observable} calls this method, it will not thereafter call {@link #onNext} or
* {@link #onComplete}.
*
* @param e
* the exception encountered by the Observable
*/
void onError(@NonNull Throwable e);
/**
* Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
* <p>
* The {@link Observable} will not call this method if it calls {@link #onError}.
*/
void onComplete();
}
下面簡單的解釋說明一下:
onNext() :普通事件,相當於 onClick() / onEvent(),所有的產生訂閱關係的Observer(觀察者)都能通過這個方法接收到傳遞過來的消息。
onCompleted(): 事件隊列完結。RxJava 不僅把每個事件單獨處理,還會把它們看做一個隊列。RxJava 規定,當不會再有新的 onNext() 發出時,需要觸發 onCompleted() 方法作爲結束標誌。
onError(): 事件隊列異常。在事件處理過程中出異常時,onError() 會被觸發,同時隊列自動終止,不允許再有事件發出。
在一個正確運行的事件序列中, onCompleted() 和 onError() 有且只有一個,並且是事件序列中的最後一個。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在隊列中調用了其中一個,就不應該再調用另一個,否則會報錯。
onSubscribe(Disposable d)裏面的Disposable對象要說一下,Disposable英文意思是可隨意使用的,用於管理訂閱關係的,如果需要取消訂閱則可以調用mDisposable.dispose()取消訂閱關係。
觀察者說完了,再來看一下被觀察者的創建方式,在Observable.java中:
/**
*......
*......
* @param <T> the element type
* @param source the emitter that is called when an Observer subscribes to the returned {@code Observable}
* @return the new Observable instance
* @see ObservableOnSubscribe
* @see ObservableEmitter
* @see Cancellable
*/
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
create(ObservableOnSubscribe<T> source)方法用於創建一個被觀察者,其中參數對象ObservableOnSubscribe<T> source 可以像上面的例子中那樣給定一個匿名對象,而這個類ObservableOnSubscribe<T>的源碼如下,它必須實現一個方法:
subscribe(@NonNull ObservableEmitter<T> emitter);
package io.reactivex;
import io.reactivex.annotations.*;
/**
* A functional interface that has a {@code subscribe()} method that receives
* an instance of an {@link ObservableEmitter} instance that allows pushing
* events in a cancellation-safe manner.
*
* @param <T> the value type pushed
*/
public interface ObservableOnSubscribe<T> {
/**
* Called for each Observer that subscribes.
* @param emitter the safe emitter instance, never null
* @throws Exception on error
*/
void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception;
}
這個subscribe(@NonNull ObservableEmitter<T> emitter)方法中傳遞了一個ObservableEmitter<T>類型的發射器參數emitter,點進這個類型我們會看到這個類的繼承關係: public interface ObservableEmitter<T> extends Emitter<T>{ },這個Emitter<T>是我們關心的,因爲它實現了幾個比較重要的方法,來看源碼:
/**
* Copyright (c) 2016-present, RxJava Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the specific language governing permissions and limitations under the License.
*/
package io.reactivex;
import io.reactivex.annotations.NonNull;
/**
* Base interface for emitting signals in a push-fashion in various generator-like source
* operators (create, generate).
*
* @param <T> the value type emitted
*/
public interface Emitter<T> {
/**
* Signal a normal value.
* @param value the value to signal, not null
*/
void onNext(@NonNull T value);
/**
* Signal a Throwable exception.
* @param error the Throwable to signal, not null
*/
void onError(@NonNull Throwable error);
/**
* Signal a completion.
*/
void onComplete();
}
是不是很驚訝,原來被觀察者內部emitter.onNext()等方法是Emitter<T>接口定義的方法,而不是觀察者Observer接口中定義的方法,這裏是需要明確區分的,有的文章說在被觀察者中調用的onNext()、onError()、onComplete()方法是觀察者中定義的方法,應該是錯的。所以在這裏特別說一下。
我們應該這樣理解,在被觀察者中發射器對象調用的onNext()、onError()、onComplete()發射信號的方法與觀察者中接收信號的方法是一一對應的,就OK了!
emitter.onNext("我愛我的故鄉!");
emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
emitter.onNext("心與心雖遠隔千里!");
emitter.onNext("但與故鄉確咫尺之間!");
emitter.onComplete();
最後給出上面例子的鏈式寫法:
package com.xw.rxjavademo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
public class MainActivity extends AppCompatActivity {
private TextView textTips;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textTips = findViewById(R.id.text_tips);
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("我愛我的故鄉!");
emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
emitter.onNext("心與心雖遠隔千里!");
emitter.onNext("但與故鄉確咫尺之間!");
emitter.onComplete();
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.v("ssss",s);
textTips.setText(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
}
或者使用Consumer<String>作爲信號的消費者!
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Consumer;
public class MainActivity extends AppCompatActivity {
private TextView textTips;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textTips = findViewById(R.id.text_tips);
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("我愛我的故鄉!");
emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
emitter.onNext("心與心雖遠隔千里!");
emitter.onNext("但與故鄉確咫尺之間!");
emitter.onComplete();
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.v("ssss",s);
textTips.setText(s);
}
});
}
}
Consumer接口的源碼定義很簡單,就一個需要重載的accept()方法:
package io.reactivex.functions;
/**
* A functional interface (callback) that accepts a single value.
* @param <T> the value type
*/
public interface Consumer<T> {
/**
* Consume the given value.
* @param t the value
* @throws Exception on error
*/
void accept(T t) throws Exception;
}
輸出結果和上面一樣!
上面算是RxJava的入門使用基礎!後面我會總結一下RxJava常用的幾種操作符和線程控制Scheduler的內容。也方便以後查閱使用!
後面持續更新!目標1000篇文章原創和1000集視頻!