綜合開源框架之RxJava/RxAndroid

* 一種幫助作異步的框架. 相似於 AsyncTask. 但其靈活性和擴展性遠遠強於前者.
* 主頁: https://github.com/ReactiveX/RxJavajava

* 中文資料:
* https://github.com/lzyzsd/Awesome-RxJavareact

* https://www.zhihu.com/question/35511144android

* 用途:
* 異步操做
* 在程序邏輯異常複雜的狀況下,仍然可讓代碼的邏輯保持簡潔git

* 配置: 添加依賴:
* compile 'io.reactivex:rxjava:1.1.3'
* compile 'io.reactivex:rxandroid:1.1.0'github


基本概念:
1. 被觀察者: Observable
  * 做用: 決定何時觸發事件以及觸發怎樣的事件
  * 建立方法:
    * Observable.just(T...) 參數爲單個的
    * Observable.from(T[]) / Observable.from(Iterable<? extends T>) 參數爲數組或Iterable
2. 觀察者: Observer
  * 做用: 當事件觸發的時候將有怎樣的行爲
  * 實現類有Observer / Subscriber
3. 訂閱: subscribe
  * 做用: 把Observable和Observer關聯起來
  * 方法:
    * observable.subscribe(observer);
    * observable.subscribe(subscriber);
4. 事件:
  * onNext():普通事件
  * onCompleted():事件隊列完結
  * onError(): 事件隊列異常
  * 須要注意的是onCompleted()和onError()是互斥的.調用了其中一個就不該該觸發另外一個.數據庫


一、建立Observable對象數組

 Observable<String> myObservable = Observable.create(  
  new Observable.OnSubscribe<String>() {  
   @Override  
   public void call(Subscriber<? super String> sub) {  
    sub.onNext("Hello, world!"); //通知訂閱者
    sub.onCompleted();  
   }  
  }  
 );

二、建立一個Subscriber來處理Observable對象發出的字符串
 網絡

Subscriber<String> mySubscriber = new Subscriber<String>() {  
  @Override  
  public void onNext(String s) { System.out.println(s); }  
   
  @Override  
  public void onCompleted() { }  
   
  @Override  
  public void onError(Throwable e) { }  
}; 

三、將定義的myObservable對象和mySubscriber對象關聯起來,這樣就完成了subscriber對observable的訂閱。框架

myObservable.subscribe(mySubscriber);

簡化版:異步

Observable<String> myObservable = Observable.just("Hello, world!");
 Action1<String> onNextAction = new Action1<String>() {  
  @Override  
  public void call(String s) {  
   System.out.println(s);  
  }  
 }; 
 myObservable.subscribe(onNextAction); 

最終簡化版:

 Observable.just("Hello, world!")  
     .subscribe(new Action1<String>() {  
     @Override  
     public void call(String s) {  
        System.out.println(s);  
     }  
 });

 

示例代碼:

1. 現有一個數組 String[] arr ={"afdsa", "bfdsa", "cfda"}, 把其中以字母"a"開頭的字符串找出來並加上"from Alpha",最後打印出新的字符串的長度

Observable
        .from(arr)
        .filter(new Func1<String, Boolean>() {
            @Override
            public Boolean call(String s) {
                return s.startsWith("a");
            }
        })
        .map(new Func1<String, String>() {
            @Override
            public String call(String s) {
                return s + " from Alpha";
            }
        })
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                System.out.println("Rxjava:" + s.length());
            }
        });
//原始Java代碼
for (int i = 0; i < arr.length; i++) {
    String temp = arr[i];
    if (temp.startsWith("a")) {
        temp += " from Alpha";
        System.out.println("Normal:" + temp.length());
    }

}

 由指定的一個 drawable 文件 id 取得圖片,並顯示在 ImageView 中,並在出現異常的時候打印 Toast 報錯:

ImageView iv = (ImageView) findViewById(R.id.imageView);
    Observable.just(R.mipmap.ic_launcher)
            .subscribeOn(Schedulers.io()) //運行在子線程中
            .map(new Func1<Integer, Drawable>() {
                @Override
                public Drawable call(Integer integer) {
                    return getResources().getDrawable(integer);
                }
            })
            .observeOn(AndroidSchedulers.mainThread()) //運行在主線程中
            .subscribe(new Action1<Drawable>() {
                @Override
                public void call(Drawable drawable) {
                    iv.setImageDrawable(drawable);
                }
            });
}

6. Scheduler
* 做用: 控制線程.指定某一段代碼在那個線程裏運行.
* 內置的Scheduler:
* 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。

* AndroidSchedulers.mainThread(): Android專用,它指定的操做將在 Android 主線程運行。

* 指定線程的方法:
* Observable.subscribeOn():指定 subscribe() 所發生的線程。
subscribeOn(Schedulers.io())
* Observable.observeOn():指定 Subscriber 所運行在的線程。
observeOn(AndroidSchedulers.mainThread())

7. 數據變換:
* 做用: 就是將事件序列中的對象或整個序列進行加工處理,轉換成不一樣的事件或事件序列
* Observable.map: 一對一的轉換

private void simpleDemo() {
           Observable
                   .just(R.mipmap.ic_launcher)
                   .map(new Func1<Integer, Drawable>() {
                       @Override
                       public Drawable call(Integer integer) {
                           return getResources().getDrawable(integer);
                       }
                   })
                   .subscribe(new Action1<Drawable>() {
                       @Override
                       public void call(Drawable drawable) {
                           imageView.setImageDrawable(drawable);
                       }
                   });
       }
相關文章
相關標籤/搜索