RxJava1.0用戶指南

目錄

目錄.png

1. Rxjava簡介

Rxjava是什么?簡單來說就是一個可以實現異步操作的庫。如果是沒有接觸過Rxjava可以直接使用RxJava2.0,并不會有任何問題。如果是已經在用RxJava1.0或者項目當中已經使用了RxJava1.0那就只能一條路走到黑了。我就是屬于后者。
相比于AsyncTask、Handler,RxJava代碼更顯得優雅簡介,調理清晰,隨著產品邏輯復雜度的增加,也依然可以使得代碼非常簡介。rxjava的異步實現是通過一種擴展的觀察者模式來實現的,先來簡單了解一下觀察者模式。

1.1 觀察者模式

觀察者模:定義對象間的一種一對多的依賴關系,使得每當一個對象改變狀態時,所有依賴于它的對象都會得到通知并被自動更新。
觸發場景

  • 事件關聯場景,需要注意關聯行為是不可拆分的,不是簡單地“組合”關系。
  • 事件多級觸發的場景。
  • 跨系統的消息處理,如消息隊列、事件總線等處理機制。

在整個觀察者模式中一共有四個角色:Subject(抽象主題、抽象被觀察者)、Concrete Subject(具體主題、具體被觀察者)、Observer(抽象觀察者)以及ConcreteObserver(具體觀察者)。四個角色關系如下:


觀察者模式UML圖.png
  • Subject(抽象主題、抽象被觀察者):抽象主題把所有被觀察者對象保存到一個集合當中,并提供一個接口,可以增加、刪除和更新觀察者對象。
  • ConcreteSubject(具體主題、具體被觀察者):將有關狀態存入具體觀察者對象,在具體主題的內部狀態發生時改變,給所有注冊過的觀察者發出通知。
  • Observer(抽象觀察者):觀察者的抽象類,定義更新接口,使得被觀察者可以在得到主題的時候更新自己。
  • ConcreteObserver(具體觀察者):實現抽象觀察者定義的更新接口,以便主題的狀態發生變化時更新自身狀態。

我們用一個具體的場景來體會一下。
說,兩國交戰,有一只隊弓箭手A在要進行埋伏。弓箭手部隊拆分為4隊A1、A2、A3,有指揮者發布命令,當收到命令時所有小隊進行射擊。這個時候指揮者就是被觀察者而每一隊弓箭手就是觀察者,代碼實現如下。
被觀察者代碼如下

/**
 * 定義被觀察者抽象類
 */
public abstract class Subject<T> {
    //創建觀察者集合
    List<Observer> mList = new ArrayList<Observer>();
    //添加觀察者
    public void add(Observer observer) {
        mList.add(observer);
    }
    //刪除觀察者
    public void remove(Observer observer) {
        if(mList!=null&&mList.contains(observer)){
            mList.remove(observer);
        }
    }
    //更新
    public abstract void notifyObserver(T t);
}

/**
 * 被觀察者具體實現
 */
public class ConcreteSubject<T> extends Subject<T> {

    @Override
    public void notifyObserver(T t) {
        for(Observer observer:mList){
            observer.update(t);
        }
    }
}

觀察者代碼如下

/**
 * 觀察者抽象接口
 */
public interface Observer<T> {

    void update(T t);
}


/**
 * 觀察者具體實現
 */
public abstract class ConcreteObserver<T> implements Observer<T> {
    String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    public String getName(){
        return name;
    }
}

這里我的觀察者是一個抽象類,實現方式類似于Rxjava的實現方式。

Main當中的代碼調用

//update類具體實現創建observer1、observer2、observer3三個觀察者
    Observer<String> observer1 = new ConcreteObserver<String>("弓箭手A1隊") {
        @Override
        public void update(String s) {
            Log.d("Observer1", getName() + "收到命令:" + s);
        }
    };
    Observer<String> observer2 = new ConcreteObserver<String>("弓箭手A2隊") {

        @Override
        public void update(String s) {
            Log.d("Observer2", getName() + "收到命令:" + s);
        }
    };
    Observer<String> observer3 = new ConcreteObserver<String>("弓箭手A3隊") {
        @Override
        public void update(String s) {
            Log.d("Observer3", getName() + "收到命令:" + s);
        }
    };
//設置被觀察者與觀察者之間關聯
    Subject<String> subject = new ConcreteSubject<String>();
    subject.add(observer1);
    subject.add(observer2);
    subject.add(observer3);
//被觀察者發送信息
    subject.notifyObserver("射殺騎白馬者!!");

打印日志

D/Observer1: 弓箭手A1隊收到命令:射殺騎白馬者!!

D/Observer2: 弓箭手A2隊收到命令:射殺騎白馬者!!

D/Observer3: 弓箭手A3隊收到命令:射殺騎白馬者!!

1.2 Rxjava中的觀察者模式

在Rxjava當中有四個基本概念,除了觀察者Observer/Subscriber和被觀察者Observable之外,ha存在訂閱subscribe以及事件

被觀察者Observable與觀察者Observer/Subscriber產生關聯的方法就是subscribe,即事件訂閱,當開始訂閱時,被觀察者Observable便開始發送事件。對于事件,Rxjava定義了三種事件類型:

  • onNext():普通的事件,用于一般的事件發送。
  • onCompleted(): 完成事件,當不再有新的onNext()事件時調用onCompleted方法作為整個事件隊列結束的標志,在一個事件隊列當中可以有多個onCompleted方法,但是只能觸發一次,一旦觸發之后,后續的事件會繼續發送,但是觀察者將不會接受事件。
  • onError(): 事件隊列異常。在事件處理過程中出現異常時,onError()會被觸發,同事隊列自動終止,與onCompleted()方法相同,onError事件也可以存在多個,但是只會觸發一次。

最為關鍵的是onCompleteonError存在互斥的關系, 兩個方法可以同時存在于事件隊列當中,但是一旦觸發其中一個方法之后,后續將不再接收事件。

RxJava關系.png

2.基本實現

RxJava的實現非常簡單

首先要在Android studio中配置gradle

implementation 'io.reactivex:rxjava:1.1.6'
implementation 'io.reactivex:rxandroid:1.2.1'

RxAndroid是RxJava在Android平臺的一些擴展,包含了一些能夠簡化Android開發的工具。(implementation與compile用法基本相同,有興趣的可以去了解一下兩者的差別)

2.1 創建觀察者

觀察者Observer決定了事件觸發的時候將有怎樣的行為。

Observer<String> observer = new Observer<String>() {
        //被觀察者調用onCompleted時觸發
        @Override
        public void onCompleted() {
            Log.d(TAG,"onCompleted");
        }
        //被觀察者調用onError時觸發
        @Override
        public void onError(Throwable e) {
            Log.d(TAG,"onError");
        }
        //被觀察者調用onNext時觸發
        @Override
        public void onNext(String s) {
            Log.d(TAG,"onNext");
        }
    };

另外一個觀察者就是Subscriber,而實際上在調用subscribe方法訂閱的時候也是把Observer轉換為了Subscriber處理的,后文我們會在RxJava的代碼中提到,先來看一看Subscriber的實現,與Observer基本一致。

Subscriber<String> subscriber = new Subscriber<String>() {
        //新增onStart方法,用來做一些初始化操作
        @Override
        public void onStart() {
            super.onStart();
        }

        @Override
        public void onCompleted() {
            Log.d(TAG,"onCompleted");
        }

        @Override
        public void onError(Throwable e) {
            Log.d(TAG,"onError");
        }

        @Override
        public void onNext(String s) {
            Log.d(TAG,"onNext");
        }
    };

這里新增加了onStart方法,這個方法會在事件開始發送前調用,實際應用中我們可以在這個方法當中做一些初始化的操作,但是這個方法一般只會在subscribe發生的線程執行(使用doOnSubscribe()方法可以改變準備線程)。

另一個不同就是Subscriber實現了另一個接口Subscription,它里面提供了兩個方法unsubscribe()和isUnsubscribed():

  • unsubscribe:用于取消訂閱,因為RxJava當中的操作可能會引起內存泄漏,在合適的地方調用該方法可以避免這個問題。
  • isUnsubscribed:用于判斷訂閱是否被取消。

2.2 創建被觀察者

它決定什么時候觸發事件以及觸發怎樣的事件。RxJava提供了多種構建被觀察者的方式,也提供了很多特殊的被觀察者,這里介紹一些比較常用的方法。

使用create創建被觀察者

Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            Log.d(TAG,"Observable Test");
            //定義事件隊列
            subscriber.onNext("aaaa");
            subscriber.onCompleted();
        }
    });

使用create( )創建Observable最基本的創建方式。可以看到,這里傳入了一個 Observable.OnSubscribe對象作為參數,當 Observable被訂閱的時候,Observable.OnSubscribe的call()方法會自動被調用,事件序列就會依照設定依次觸發。這樣,由被觀察者調用了觀察者的回調方法,就實現了由被觀察者向觀察者的事件傳遞,即觀察者模式。

除了create方法之外,還存在其他的常用的構建方式。

just()

使用just( ),將為你創建一個Observable并自動為你調用onNext( )發射數據。通過just( )方式 直接觸發onNext(),just中傳遞的參數將直接在Observer的onNext()方法中接收到。

Observable<String> observable =  Observable.just("hello");
observable.subscribe(subscriber);

輸出log

 D/MainActivity: onNext
 D/MainActivity: onCompleted

from()

from()方法將傳入的數組Iterable拆分成具體對象后,自動調用onNext方法依次發送,再發送結束后發送onCompleted結束整個事件。

//定義要發送的事件集合
    List<String> mList = new ArrayList<String>();
    mList.add("aaaa");
    mList.add("bbbb");
    mList.add("cccc");
    mList.add("dddd");
    //定義Observable
    Observable<String> observable = Observable.from(mList);
    //進行訂閱,開始發送事件
    observable.subscribe(subscriber);
D/MainActivity: onNextaaaa
D/MainActivity: onNextbbbb
D/MainActivity: onNextcccc
D/MainActivity: onNextdddd
D/MainActivity: onCompleted

defer()

通過defer()方法創建Observable,當觀察者訂閱時,才創建Observable,并且針對每個觀察者創建都是一個新的Observable。以何種方式創建這個Observable對象,當滿足回調條件后,就會進行相應的回調。還是通過代碼來看。

    //定義一個被觀察者
    Observable<String> observable = Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {

                Observable<String> mObservable = Observable.create(new Observable.OnSubscribe<String>() {
                    @Override
                    public void call(Subscriber<? super String> subscriber) {
                        subscriber.onNext("事件訂閱開始");
                    }
                });
                return mObservable;
            }
        });
        //訂閱事件1,沒產生一個訂閱就會生成一個新的observable對象
        observable.subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG,"觀察者2訂閱事件    "+s);
            }
        });
        //訂閱事件2,沒產生一個訂閱就會生成一個新的observable對象
        observable.subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG,"觀察者1訂閱事件    "+s);
            }
        });

打印輸出運行結果

D/MainActivity: 觀察者2訂閱事件    事件訂閱開始
D/MainActivity: 觀察者1訂閱事件    事件訂閱開始

使用defer()方法,每當產生新的訂閱事件時都會生成一個新的mObservable對象。

這里用到了不完整定義的回調Action,它就相當于我們之前定義的subscriber,但是其只針對onNext事件做處理,后續我們介紹subscribe()時再詳細介紹。

interval()

創建一個按固定時間間隔發射整數序列的Observable,可用作定時器。即按照固定時長調用onNext()方法。

    Observable<Long> observable = Observable.interval(1, TimeUnit.SECONDS);
        observable.subscribe(new Action1<Long>() {
            @Override
            public void call(Long aLong) {
                Log.d(TAG,"訂閱時長為"+aLong);
            }
        });

輸出結果日志:

D/MainActivity: 訂閱時長為0
D/MainActivity: 訂閱時長為1
D/MainActivity: 訂閱時長為2
D/MainActivity: 訂閱時長為3
D/MainActivity: 訂閱時長為4
D/MainActivity: 訂閱時長為5
D/MainActivity: 訂閱時長為6
......

每隔一秒發送一個事件交給觀察者處理。

timer()

該方法可以在一定延遲之后發送特定事件。

//定義被觀察者,在2000毫秒后開始發送事件
    Observable<Long> observable = Observable.timer(2000,TimeUnit.MILLISECONDS);
        Subscriber<Long> subscriber = new Subscriber<Long>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Long aLong) {
                Log.d(TAG,"收到事件啦");
            }
        };
        Log.d(TAG,"開始訂閱發送事件");
        observable.subscribe(subscriber);

輸出日志

16:09:38.524 D/MainActivity: 開始訂閱發送事件
16:09:40.524 D/MainActivity: 收到事件啦

可以看到在訂閱之后,過了2000毫秒observable開始發送事件。

到這里我們創建了觀察者Observable與觀察者Observer/Subscriber,只到這一步我們會產生很多疑問:interval發送事件如何取消訂閱、上面提到的Action到底什么時候會用到,為什么Subscriber的start方法只能在默認線程調用等等問題。這個時候就該到我們的subscribe登場了。

2.3 Subscribe訂閱

創建完ObservableObserver/Subscriber,使用subscribe那我們整個訂閱過程就就完成了,在上面的代碼也有提到,整個調用方式如下

observable.subscribe(subscriber);

我們來簡單看一下subscribe()方法的源碼。

static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
        subscriber.onStart();
        observable.onSubscribe.call(subscriber);
        return Subscription;
    }

這里提出了關鍵的流程代碼,結合訂閱的調用過程我們分析整個訂閱流程。

  • 首先是傳進來的兩個參數SubscriberObservable分別對應我們調用時的subscriberobservable
  • 訂閱開始后,首先執行的是subscriber.onStart()方法,也就是我們觀察者的onStart方法,這也就解釋了為什么onStart方法只可以在默認線程當中執行,因為我們指定線程只可以指定observable所對應線程以及observable對應直屬下級Subscriber(好吧這里又是一個坑,后文我們會做解釋)所在線程。
  • 接下來調用observable當中的onSubscribe.call方法,我們的整個事件序列就定義在這里,調用call方法開始發送事件。
  • 返回值Subscription,之前在介紹觀察者Subscriber時我們有提到,Subscriber實現了這個接口,用于提供解除訂閱以及判斷訂閱是否連接的方法,在訂閱完成之后返回Subscription供外部調用。

不完整定義回調

subscribe參數表.png

從上圖可以看出,subscribe方法的參數除了SubscriberObserver之外,還有Action類,這就是將要介紹的不完整定義回調

        Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("aaaaa");
                subscriber.onError(new NullPointerException());
            }
        });
        //只對事件序列中的onNext做出響應
        Action1<String> action1 = new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG,"action1--->onNext  "+s);
            }
        };
        //只對事件序列中的onError做出響應
        Action1<Throwable> action11 = new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                Log.d(TAG,"action11--->onError  "+throwable.getMessage());
            }
        };
        //只對事件序列中的onCompleted做出響應
        Action0 action0 = new Action0() {
            @Override
            public void call() {
                Log.d(TAG,"action11--->onCompleted  ");
            }
        };
        //訂閱事件,只處理onNext事件
        observable.subscribe(action1);
        //訂閱事件,只處理onNext和onError事件
        observable.subscribe(action1,action11);
        //訂閱事件,處理onNext、onError和onCompleted事件
        observable.subscribe(action1,action11,action0);

2.4 RxJava鏈式調用

在實際應用中,我們可以采用鏈式調用的方式把上述步驟串聯起來,從而使得代碼結構更加簡潔,優雅。

//定義將要發射的數組
    String[] strs = {"1", "2", "3", "4", "5"};
    //from操作符可以把數組當中的數據逐條發送出去
        Observable.from(strs)
        //調用flatMap操作符把String類型轉換為新的Observable<String>并開始發送事件后文會進行介紹。
            .flatMap(new Func1<String, Observable<String>>() {
            @Override
            public Observable<String> call(String s) {
                Log.d("testRX---map",s);
                //需要把String類型轉換成的Observable對象
                return Observable.create(new Observable.OnSubscribe<String>() {
                    @Override
                    public void call(Subscriber<? super String> subscriber) {
                        subscriber.onNext("test");
                    }
                });
            }
        }).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                //處理完成事件
            }
            @Override
            public void onError(Throwable e) {
                //處理error事件
            }
            @Override
            public void onNext(String s) {
                //處理普通的onNext事件
            }
        });

在這個例子中用到了變換操作符flatMap,在實際應用中也會經常用到,下面我們詳細介紹一下。

3. 變換操作符

變換操作符的作用是對Observable發射的數據按照一定規則做一些變換操作,然后將變換后的數據發射出去。變換操作符有map,flatMap,switchMap,flatMapIterable,buffer,groupBy等。

map

map操作符就是通過制定一個Func1對象,將原Observable對象轉換為另一個Observable對象并發射。

        //定義初始事件序列數組
        Integer[] ints = {1, 2, 3};
        //調用from逐個發射數據
        //map方法把Intger類型轉換為String類型
        Observable.from(ints).map(new Func1<Integer, String>() {
            @Override
            public String call(Integer i) {
                //對Integer數據進行處理,轉換成String類型返回
                return i + "號玩家";
            }
        }).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG,s+"加入游戲");
            }
        });

運行輸出結果:

D/MainActivity: 1號玩家加入游戲
D/MainActivity: 2號玩家加入游戲
D/MainActivity: 3號玩家加入游戲

這里就比較有意思了,map方法怎么就把一種數據類型轉換成了另一種數據類型呢
我們看一下map的源碼

public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
    return lift(new OperatorMap<T, R>(func));
}

//這里新建了一個Operator對象,核心功能代碼如下
public final class OperatorMap<T, R> implements Operator<R, T> {
    final Func1<? super T, ? extends R> transformer;

    public OperatorMap(Func1<? super T, ? extends R> transformer) {
        this.transformer = transformer;
    }

    @Override
    public Subscriber<? super T> call(final Subscriber<? super R> o) {
        MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
        o.add(parent);
        return parent;
    }
}

public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
        return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe, operator));
    }

這里新建一個newSubscriber并與原observable訂閱的Subscriber關聯起來,left方法本身也返回一個新建的被觀察者newObservable。由此變為,當產生事件訂閱時,實際上是newObservable訂閱了事件,之后而通知原observable開始發送事件,原observable發送的事件發送向newSubscriber,再發送給Subscriber

整個事件的流程變化如下:


訂閱事件變化.png

flatMap

flatMap也是用來做類型轉換,不同于map的是,flatMap轉換后得到的是一個Observable對象。代碼實現如下:

//interval方法創建Observable對象,每隔1秒發送一個事件
//經過flatMap方法變化,將long類型的事件變換為一個新的Observable對象發射出去
subscription = Observable.interval(1, TimeUnit.SECONDS).flatMap(new Func1<Long, Observable<String>>() {
            @Override
            public Observable<String> call(final Long aLong) {
                return Observable.create(new Observable.OnSubscribe<String>(){
                    @Override
                    public void call(Subscriber<? super String> subscriber) {
                        Log.d("testRX---next","test"+aLong);
                        subscriber.onNext(aLong+"");
                    }
                });
            }
            //定義Subscriber對變換后的事件進行接收
        }).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError");
            }

            @Override
            public void onNext(String s) {
                Log.d(TAG, "onNext" + s);
            }
        });

打印輸出結果:

D/testRX---next: test0
D/MainActivity: onNext0
D/testRX---next: test1
D/MainActivity: onNext1
D/testRX---next: test2
D/MainActivity: onNext2
D/MainActivity: onNext3
......

flatMap的原理比較復雜,我們還是通過源碼來分析

public final <R> Observable<R> flatMap(Func1<? super T, ? extends Observable<? extends R>> func) {
    if (getClass() == ScalarSynchronousObservable.class) {
        return ((ScalarSynchronousObservable<T>)this).scalarFlatMap(func);
    }
    return merge(map(func));
}

首先在這里它調用了map方法,在前面我們分析過,map方法會生成一個新的Observable對象,并改變事件的訂閱順序,接下來執行到merge方法,merge方法做了什么呢

 public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
        return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe, operator));
    }
    
public final class OnSubscribeLift<T, R> implements OnSubscribe<R> {
    
    public OnSubscribeLift(OnSubscribe<T> parent, Operator<? extends R, ? super T> operator) {
        this.parent = parent;
        this.operator = operator;
    }

    @Override
    public void call(Subscriber<? super R> o) {
       Subscriber<? super T> st = hook.onLift(operator).call(o);
                 // new Subscriber created and being subscribed with so 'onStart' it
        st.onStart();
        parent.call(st);
    }
}
    

這里會把每一個創建出來的 Observable 發送的事件,都被匯入同一個 Observable ,這個 Observable 負責將這些事件統一交給 Subscriber 的回調方法。

buffer

buffer操作符將源Observable變換為一個新的Observable,這個新的Observable每次發射一組列表值而不是一個一個發射。和buffer操作類似的還有window操作符,只不過window操作符發射的是Observable而不是數據列表。

Observale.just(1,2,3,4,5,6).buffer(3).subscribe(new Action1<List<Integer>>() {
    @Override
    public void call(List<Integer> integers){
        for(Integer integer:integers){
            Log.d(TAG,"buffer"+integer);
        }
  Log.d(TAG,"---------");
    }
});

輸出日志:

D/MainActivity: buffer1
D/MainActivity: buffer2
D/MainActivity: buffer3
D/MainActivity: ---------
D/MainActivity: buffer4
D/MainActivity: buffer5
D/MainActivity: buffer6
D/MainActivity: ---------

fliter

filter()操作符根據test()方法中,根據自己想過濾的數據加入相應的邏輯判斷,返回true則表示數據滿足條件,返回false則表示數據需要被過濾。最后過濾出的數據將加入到新的Observable對象中,方便傳遞給Observer想要的數據形式。

Observable.just(1,2,3,4,5,6).filter(new Func1<Integer, Boolean>() {
    @Override
    public Boolean call(@NonNull Integer integer){
        if(integer > 3){
            return true;
        }
        return false;
    }
}).subscribe(new Action1<Integer>() {
    @Override
    public void call(Integer integer){
        Log.d(TAG,integer+"");
    }
});

輸出結果

D/MainActivity: onSubscribe
D/MainActivity: onNext
D/MainActivity: Hello World!
D/MainActivity: 4
D/MainActivity: 5
D/MainActivity: 6

4. 線程調度

默認情況下,在哪個線程調subscribe(),就會在哪個線程生產事件;在哪個線程生產事件,就在哪個線程消費事件。如果需要切換線程,則需要 Scheduler (調度器)

在RxJava 中,Scheduler,相當于線程控制器,RxJava 通過它來指定每一段代碼應該運行在什么樣的線程。RxJava 已經內置了幾個 Scheduler ,它們已經適合大多數的使用場景。

Scheduler 的 API

  • Schedulers.immediate(): 直接在當前線程運行,相當于不指定線程。這是默認的 Scheduler。
  • Schedulers.newThread(): 總是啟用新線程,并在新線程執行操作。
  • Schedulers.io(): I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的 Scheduler。行為模式和 newThread() 差不多,區別在于 io() 的內部實現是用一個無數量上限的線程池,可以重用空閑的線程,因此多數情況下 io() 比 newThread() 更有效率。不要把計算工作放在 io() 中,可以避免創建不必要的線程。
  • Schedulers.computation(): 計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小為 CPU 核數。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時間會浪費 CPU。
  • Android 還有一個專用的 AndroidSchedulers.mainThread(),它指定的操作將在 Android 主線程運行。

有了這幾個 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 兩個方法來對線程進行控制了。

  • subscribeOn(): 指定Observable(被觀察者)所在的線程,或者叫做事件產生的線程。
  • observeOn(): 指定 Observer(觀察者)所運行在的線程,或者叫做事件消費的線程。
    實例如下:
        Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                Log.d(TAG, Thread.currentThread().getName());
                subscriber.onNext("aaaa");
                subscriber.onCompleted();
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {

                    @Override
                    public void onCompleted() {
                        Log.d(TAG, "onCompleted");
                        Log.d(TAG, Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d(TAG, "onNext " + s);
                    }
                });

輸出日志:

D/MainActivity: RxIoScheduler-2
D/MainActivity: onNext aaaa
D/MainActivity: onCompleted
D/MainActivity: main

總結

RxJava在剛剛接觸的時候使用起來會覺得比較別扭,主要是與java的方式存在一些差異,使用一段時間之后就會產生“RxJava太好用了”的感覺。一些原理性的東西這里介紹的比較簡單,大家有興趣的可以看一下給 Android 開發者的 RxJava 詳解,介紹的很詳細。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容