Android RxJava應(yīng)用:合并數(shù)據(jù)源 & 同時展示

前言

Rxjava载慈,由于其基于事件流的鏈式調(diào)用惭等、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發(fā)者的歡迎辞做。

如果還不了解RxJava,請看文章:Android:這是一篇 清晰 & 易懂的Rxjava 入門教程

  • RxJava如此受歡迎的原因稚补,在于其提供了豐富 & 功能強大的操作符框喳,幾乎能完成所有的功能需求
  • 今天,我將為大家?guī)?Rxjava創(chuàng)建操作符的常見開發(fā)應(yīng)用場景:合并數(shù)據(jù)源需求 乍惊,并結(jié)合RetrofitRxJava 實現(xiàn)润绎,希望大家會喜歡诞挨。

Carson帶你學(xué)RxJava系列文章,包括 原理棍郎、操作符坝撑、應(yīng)用場景粮揉、背壓等等抚笔,請關(guān)注看文章:Android:這是一份全面 & 詳細的RxJava學(xué)習指南


目錄

示意圖

1. 需求場景

示意圖

2. 功能說明

即辐宾,同時向2個數(shù)據(jù)源獲取數(shù)據(jù) -> 合并數(shù)據(jù) -> 統(tǒng)一展示到客戶端


3. 具體實現(xiàn)

此處采用Merge() & Zip()操作符進行講解膨蛮,其中:

  • Merge()例子 :實現(xiàn)較為簡單的從(網(wǎng)絡(luò) + 本地)獲取數(shù)據(jù) & 統(tǒng)一展示
  • Zip()例子:結(jié)合RetrofitRxJava敞葛,實現(xiàn)較為復(fù)雜的合并2個網(wǎng)絡(luò)請求向2個服務(wù)器獲取數(shù)據(jù) & 統(tǒng)一展示

3.1 采用 Merge()操作符

  • 具體實現(xiàn)

關(guān)于操作符Merge() 的使用請看文章:Android RxJava:組合 / 合并操作符 詳細教程

// 用于存放最終展示的數(shù)據(jù)
        String result = "數(shù)據(jù)源來自 = " ;
       
        /*
         * 設(shè)置第1個Observable:通過網(wǎng)絡(luò)獲取數(shù)據(jù)
         * 此處僅作網(wǎng)絡(luò)請求的模擬
         **/
        Observable<String> network = Observable.just("網(wǎng)絡(luò)");

        /*
         * 設(shè)置第2個Observable:通過本地文件獲取數(shù)據(jù)
         * 此處僅作本地文件請求的模擬
         **/
        Observable<String> file = Observable.just("本地文件");


        /*
         * 通過merge()合并事件 & 同時發(fā)送事件
         **/
        Observable.merge(network, file)
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(String value) {
                        Log.d(TAG, "數(shù)據(jù)源有: "+ value  );
                        result += value + "+";
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "對Error事件作出響應(yīng)");
                    }

                    // 接收合并事件后惹谐,統(tǒng)一展示
                    @Override
                    public void onComplete() {
                        Log.d(TAG, "獲取數(shù)據(jù)完成");
                        Log.d(TAG,  result  );
                    }
                });
  • 測試結(jié)果
示意圖

3.2 采用Zip()操作符

關(guān)于操作符Zip() 的使用請看文章:Android RxJava:組合 / 合并操作符 詳細教程

  • 功能說明
    在該例中,我將結(jié)合結(jié)合 RetrofitRxJava鸿秆,實現(xiàn):

    1. 從不同數(shù)據(jù)源(2個服務(wù)器)獲取數(shù)據(jù)卿叽,即 合并網(wǎng)絡(luò)請求的發(fā)送
    2. 統(tǒng)一顯示結(jié)果
  • 實現(xiàn)方案
    采用Get方法 對 金山詞霸API 發(fā)送2個網(wǎng)絡(luò)請求(將英文翻譯成中文,翻譯2次) & 將2次翻譯的結(jié)果一起顯示埠戳。

采用 Gson 進行數(shù)據(jù)解析

金山詞典
  • 步驟說明
    1. 添加依賴
    2. 創(chuàng)建 接收服務(wù)器返回數(shù)據(jù) 的類
    3. 創(chuàng)建 用于描述網(wǎng)絡(luò)請求 的接口
    4. 創(chuàng)建 Retrofit 實例
    5. 創(chuàng)建 網(wǎng)絡(luò)請求接口實例 并 配置網(wǎng)絡(luò)請求參數(shù)
    6. 發(fā)送網(wǎng)絡(luò)請求
    7. 發(fā)送網(wǎng)絡(luò)請求
    8. 對返回的數(shù)據(jù)進行處理

本實例側(cè)重于說明 RxJava 的線程控制整胃,關(guān)于Retrofit的使用請看文章:這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解)

  • 步驟實現(xiàn)
步驟1: 添加依賴

a. 在 Gradle加入Retrofit庫的依賴

build.gradle

dependencies {

// Android 支持 Rxjava
// 此處一定要注意使用RxJava2的版本
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

// Android 支持 Retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'

// 銜接 Retrofit & RxJava
// 此處一定要注意使用RxJava2的版本
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

// 支持Gson解析
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

}

b. 添加 網(wǎng)絡(luò)權(quán)限
AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
步驟2:創(chuàng)建 接收服務(wù)器返回數(shù)據(jù) 的類
  • 金山詞霸API 的數(shù)據(jù)格式說明如下:
// URL模板
http://fy.iciba.com/ajax.php

// URL實例
http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=hello%20world

// 參數(shù)說明:
// a:固定值 fy
// f:原文內(nèi)容類型屁使,日語取 ja奔则,中文取 zh,英語取 en酬蹋,韓語取 ko范抓,德語取 de食铐,西班牙語取 es,法語取 fr象泵,自動則取 auto
// t:譯文內(nèi)容類型斟叼,日語取 ja朗涩,中文取 zh,英語取 en扒腕,韓語取 ko,德語取 de皆的,西班牙語取 es蹋盆,法語取 fr,自動則取 auto
// w:查詢內(nèi)容
  • 示例
API格式說明
  • 根據(jù) 金山詞霸API 的數(shù)據(jù)格式楞抡,創(chuàng)建 接收服務(wù)器返回數(shù)據(jù) 的類:

為了演示是兩個網(wǎng)絡(luò)請求析藕,所以對應(yīng)設(shè)置2個接收服務(wù)器的數(shù)據(jù)類

<-- Translation1.java -->
public class Translation1 {
    private int status;
    private content content;
    private static class content {
        private String from;
        private String to;
        private String vendor;
        private String out;
        private int errNo;
    }

   //定義 輸出返回數(shù)據(jù) 的方法
    public String show() {

        return ("第1次翻譯=" + content.out);

    }
}

<-- Translation2.java -->
public class Translation2 {
    private int status;
    private content content;
    private static class content {
        private String from;
        private String to;
        private String vendor;
        private String out;
        private int errNo;
    }

 //定義 輸出返回數(shù)據(jù) 的方法
    public String show() {

        return ("第2次翻譯=" + content.out);

    }
}
步驟3:創(chuàng)建 用于描述網(wǎng)絡(luò)請求 的接口

采用 注解 + Observable<...>接口描述 網(wǎng)絡(luò)請求參數(shù)

GetRequest_Interface.java

public interface GetRequest_Interface {

    // 網(wǎng)絡(luò)請求1
    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20world")
    Observable<Translation1> getCall();

    // 網(wǎng)絡(luò)請求2
    @GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20china")
    Observable<Translation2> getCall_2();

    // 注解里傳入 網(wǎng)絡(luò)請求 的部分URL地址
    // Retrofit把網(wǎng)絡(luò)請求的URL分成了兩部分:一部分放在Retrofit對象里账胧,另一部分放在網(wǎng)絡(luò)請求接口里
    // 如果接口里的url是一個完整的網(wǎng)址治泥,那么放在Retrofit對象里的URL可以忽略
    // 采用Observable<...>接口
    // getCall()是接受網(wǎng)絡(luò)請求數(shù)據(jù)的方法

}
接下來的步驟均在MainActivity.java內(nèi)實現(xiàn)(請看注釋)

MainActivity.java

public class MainActivity extends AppCompatActivity {


        private static final String TAG = "Rxjava";


        // 定義Observable接口類型的網(wǎng)絡(luò)請求對象
        Observable<Translation1> observable1;
        Observable<Translation2> observable2;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // 步驟1:創(chuàng)建Retrofit對象
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://fy.iciba.com/") // 設(shè)置 網(wǎng)絡(luò)請求 Url
                    .addConverterFactory(GsonConverterFactory.create()) //設(shè)置使用Gson解析(記得加入依賴)
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
                    .build();

            // 步驟2:創(chuàng)建 網(wǎng)絡(luò)請求接口 的實例
            GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

            // 步驟3:采用Observable<...>形式 對 2個網(wǎng)絡(luò)請求 進行封裝
            observable1 = request.getCall().subscribeOn(Schedulers.io()); // 新開線程進行網(wǎng)絡(luò)請求1
            observable2 = request.getCall_2().subscribeOn(Schedulers.io());// 新開線程進行網(wǎng)絡(luò)請求2
            // 即2個網(wǎng)絡(luò)請求異步 & 同時發(fā)送

            // 步驟4:通過使用Zip()對兩個網(wǎng)絡(luò)請求進行合并再發(fā)送
            Observable.zip(observable1, observable2,
                    new BiFunction<Translation1, Translation2, String>() {
                        // 注:創(chuàng)建BiFunction對象傳入的第3個參數(shù) = 合并后數(shù)據(jù)的數(shù)據(jù)類型
                        @Override
                        public String apply(Translation1 translation1,
                                            Translation2 translation2) throws Exception {
                            return translation1.show() + " & " +translation2.show();
                        }
                    }).observeOn(AndroidSchedulers.mainThread()) // 在主線程接收 & 處理數(shù)據(jù)
                    .subscribe(new Consumer<String>() {
                        // 成功返回數(shù)據(jù)時調(diào)用
                        @Override
                        public void accept(String combine_infro) throws Exception {
                            // 結(jié)合顯示2個網(wǎng)絡(luò)請求的數(shù)據(jù)結(jié)果
                            Log.d(TAG, "最終接收到的數(shù)據(jù)是:" + combine_infro);
                        }
                    }, new Consumer<Throwable>() {
                        // 網(wǎng)絡(luò)請求錯誤時調(diào)用
                        @Override
                        public void accept(Throwable throwable) throws Exception {
                            System.out.println("登錄失敗");
                        }
                    });
        }
}

  • 測試結(jié)果
示意圖

4. 總結(jié)

  • 本文主要講解了 Rxjava的實際開發(fā)需求場景:合并數(shù)據(jù)源需求 败潦,并結(jié)合RetrofitRxJava 實現(xiàn)
  • Carson帶你學(xué)RxJava系列文章:

入門
Carson帶你學(xué)Android:這是一篇清晰易懂的Rxjava入門教程
Carson帶你學(xué)Android:面向初學(xué)者的RxJava使用指南
Carson帶你學(xué)Android:RxJava2.0到底更新了什么劫扒?
原理
Carson帶你學(xué)Android:圖文解析RxJava原理
Carson帶你學(xué)Android:手把手帶你源碼分析RxJava
使用教程:操作符
Carson帶你學(xué)Android:RxJava操作符教程
Carson帶你學(xué)Android:RxJava創(chuàng)建操作符
Carson帶你學(xué)Android:RxJava功能性操作符
Carson帶你學(xué)Android:RxJava過濾操作符
Carson帶你學(xué)Android:RxJava組合/合并操作符
Carson帶你學(xué)Android:RxJava變換操作符
Carson帶你學(xué)Android:RxJava條件/布爾操作符
實戰(zhàn)
Carson帶你學(xué)Android:什么時候應(yīng)該使用Rxjava粟关?(開發(fā)場景匯總)
Carson帶你學(xué)Android:RxJava線程控制(含實例講解)
Carson帶你學(xué)Android:圖文詳解RxJava背壓策略
Carson帶你學(xué)Android:RxJava环戈、Retrofit聯(lián)合使用匯總(含實例教程)
Carson帶你學(xué)Android:優(yōu)雅實現(xiàn)網(wǎng)絡(luò)請求嵌套回調(diào)
Carson帶你學(xué)Android:網(wǎng)絡(luò)請求輪詢(有條件)
Carson帶你學(xué)Android:網(wǎng)絡(luò)請求輪詢(無條件)
Carson帶你學(xué)Android:網(wǎng)絡(luò)請求出錯重連(結(jié)合Retrofit)
Carson帶你學(xué)Android:合并數(shù)據(jù)源
Carson帶你學(xué)Android:聯(lián)想搜索優(yōu)化
Carson帶你學(xué)Android:功能防抖
Carson帶你學(xué)Android:從磁盤/內(nèi)存緩存中獲取緩存數(shù)據(jù)
Carson帶你學(xué)Android:聯(lián)合判斷


歡迎關(guān)注Carson_Ho的簡書

不定期分享關(guān)于安卓開發(fā)的干貨,追求短性昭、平、快汹族,但卻不缺深度


請點贊夸政!因為你的鼓勵是我寫作的最大動力榴徐!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坑资,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子仿便,更是在濱河造成了極大的恐慌攒巍,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異常柄,居然都是意外死亡,警方通過查閱死者的電腦和手機卷玉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門相种,熙熙樓的掌柜王于貴愁眉苦臉地迎上來品姓,“玉大人,你說我怎么就攤上這事衬潦≈菜郑” “怎么了弦牡?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵驾锰,是天一觀的道長走越。 經(jīng)常有香客問我买喧,道長,這世上最難降的妖魔是什么淤毛? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任低淡,我火速辦了婚禮,結(jié)果婚禮上何荚,老公的妹妹穿的比我還像新娘猪杭。我一直安慰自己,他們只是感情好戒傻,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布需纳。 她就那樣靜靜地躺著艺挪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪口蝠。 梳的紋絲不亂的頭發(fā)上掂器,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天国瓮,我揣著相機與錄音,去河邊找鬼禁漓。 笑死孵睬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的秘狞。 我是一名探鬼主播蹈集,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼拢肆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了支示?” 一聲冷哼從身側(cè)響起鄙才,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎据途,沒想到半個月后叙甸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裆蒸,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年佛致,在試婚紗的時候發(fā)現(xiàn)自己被綠了俺榆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片装哆。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡定嗓,死狀恐怖萍桌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情恃逻,我是刑警寧澤藕施,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布裳食,位于F島的核電站,受9級特大地震影響胞谈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卿捎,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一午阵、第九天 我趴在偏房一處隱蔽的房頂上張望享扔。 院中可真熱鬧,春花似錦籽懦、人聲如沸氛魁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽或链。三九已至,卻和暖如春澳盐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盆繁。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工油昂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留倾贰,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓安寺,卻偏偏與公主長得像首尼,于是被迫代替她去往敵國和親软能。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容