Rxjava梳理(2)--Transform,Operator

關于Rxjava的第二篇文章來了,前幾天由于我情緒不佳暫時中斷幾天。今天終于恢復心情,開始繼續自己梳理工作。

在之前的文章《Rxjava梳理(1)--Observable,Observer,subscribe》里講到了Observable,observer,subscribe這些Rxjava中的基本概念。本篇文章想梳理一下Rxjava里面最有用以及最難以理解的一個特性:"變換(Transform)"。有人會覺得Rxjava很好用,又有些人會覺得Rxjava很難理解,絕大多數正是因為Rxjava的變換特性

用例子來說明吧:假設有一個方法是要把一個字符串顯示在文本控件上,一般方法如下

  public void displayText(String text){
   textView.setText(text);
  }
   

而如果運用上一篇文章所講的,就應該這樣寫

    public void displayText(String text){
      Observable.just(text).subscribe( new Action1<String>(){
         public void call(String s){
            textView.setText(s);
        }


});  
 
    }

這個時候如果有這樣的一個需求,需要對該字符串在顯示之前,先做一些處理轉換成新的字符串再打印,應該如何做呢?這時候我們可以這樣做

   public void displayText(String text){
     String newText = convertToNewText(text);
    Observable.just(newText).subscribe( new Action1<String>(){
         public void call(String s){
            textView.setText(s);
        }
});  
  }

這樣做有一個問題就是如果我們是從第三方庫里得到的是封裝了該字符串對象的Observable對象應該如何做呢?當然這樣,我們也可以這樣做

    public void displayText(String text){
     Observable.just(text).subscribe( new Action1<String>(){
         public void call(String s){
            String newText = convertToNewText(s);
            textView.setText(newText);
        }
});  
   }

這種方法也有一個問題,就是 call方法里的方法明顯應該放在主線程里,如果convertToNewText()方法是一個非常耗時的方法的話就會對應用程序的性能造成很大的影響,所以盡量保證call方法里的處理邏輯簡潔是很重要的事情,這就使得我們可以嘗試map()方法來嘗試解決這個問題

    public void displayText(String text){
      Observable.just(text).map(new Func1<String,String>(){
           
          public String call(String text){
             return convertToNewText(text);   
           }

      }).subscribe( new Action1<String>(){
         public void call(String s){
            textView.setText(s);
        }
        });

    }

通過這個例子可以看出來,map方法通過Func1這個對象把一個字符串轉換為另一個字符串,并在訂閱的方法里顯示出這個改變了的字符串,和之前的方法比,是不是邏輯更加清晰些了呢?當然,Func1對象不僅僅可以轉換成相同類型的對象,還可以把一種類型的對象轉換成其他類型的對象,比如說上面的例子,如果我們想顯示該字符串的長度呢?

 public void displayLengthOfText(String text){
  Observable.just(text).map(new Func1<String,Integer>(){
    public Integer call(String text){
     return text.length(); 
  }
}).map(new Func1<Integer,String>(){
  public String call(int length){
   return Integer.toString(length); 
}
}).subscribe(new Action1<Integer>(){
   public void call(String length){
         textView.setText(length);
  }
})
}

可見這種方式把每一種轉換都單獨放到了一個方法里,讓邏輯更加清晰。
如果情況更加復雜了呢,比如,我得到一個字母列表比如{"a","b","c"}。這個列表里面的元素又需要到單詞表里搜出以該字母為首字母的單詞列表,比如以a為首字母的列表就會有{"cat","career","chat"...},而我訂閱的方法就需要把這些單詞打印出來,這樣一個需求如何實現呢?我們可以這樣來做

public void displayWord(List<String> letters){
   Observable.from(letters).map(new Func1<String,List<String>>(){
           public List<String> call(String letter){
     List<String> words = getWordsByLetter(letter);
               return words
   }  
   }).subscribe(new Action1<List<String>>(){
         public void call(List<String> words){
             for(String word:words){
                System.out.println(word);
             }
        }
});
}
     

這種實現的問題就會把過多的代碼都放到了Action1類的方法里,不利于對每一個字符串對象進行變換處理。這時候flatMap()方法被提了出來

   public void displayWord(List<String> letters){
     Observable.from(letters).flatMap(new Func1<String,Observable<String>>(){
            public Observable<String> call(String letter){
          Observable<String> words= Observable.from(getWordsByLetter(letter));
           return words;
  }      
} ).subscribe(new Action1<String>(){
      public void call(String word){
         
            System.out.println(word);
     }
});
  }

從上面的例子可以看到,flatMap里的Func1對象里的call()方法返回的是Observable對象.flatMap()方法的原理如下:

  1. flatMap()方法返回一個大的Observable對象
  2. call()方法并不是返回Observable對象給步驟1的大Observable對象,而是把它的事件(即String對象)傳給了大的Observable對象
  3. 這樣大的Observable對象匯聚了所有的匿名類中生成的Observable對象里的事件,統一發給了Subscriber對象。

要了解這些轉換的原理的話,就需要了解lift(Operator)方法,該方法的一些重要的代碼如下:

  public<R> Observable<R> lift(Operator<? extends R,? super T> oprator){
          return Observable.create(new OnSubscibe<R>(){

public void call(Subscriber subscriber){

   Subscriber newSubscriber = operator.call(subscriber);
  newSubscriber.onStart();
  onSubscribe.call(newSubscriber);
}

});
   }

需要解釋一下lift() 方法的原理:

  1. lift()方法生成了一個新的Observable對象,和原來的Observable對象并存。
  2. 當lift()方法生成的新的Observable對象調用subscribe()方法的時候,該Obsersable的OnSubscriber對象的call()方法被調用,就是上面代碼塊中的方法。
  3. call方法里首先用了operator.call()方法用我們調用的Subscriber對象生成了一個新的Subscriber對象,并且把兩者連接起來
  4. 后面的onSubscribe方法是原始的Observable對象里面的OnSubscribe對象,通過call方法調用了新的Subscriber對象里的方法,實際上也就間接調用了原來的Subscriber對象里的方法。

這一篇文章的內容相對比較抽象和晦澀,我可能未必講清楚了,只是梳理了一下自己的思路,歡迎大家和我交流,共同成長。

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

推薦閱讀更多精彩內容