RxJava for Android 開發使用的開源框架

RxJava 出來很久了,以至于現在大紅大紫。在 Android 平臺中的影響更是不可言語,很多新開源項目中也紛紛引入了她。但我一直因為各種原因沒有動手揭開她神秘的面紗。目前 Rx (ReactiveX) 對 Android 支持已經非常強大, 從數據庫到業務邏輯異步處理,再到與 MVP 設計模式的結合都已經有相對成熟解決方案?,F在正是入手的好時機?,F在網絡上有關于 RxJava 的文章很多,在此就不累贅她的好處和使用方法,感興趣可以自行學習。

說明: 本人對 RxJava 的理解不是很深刻,目前只處于會用的階段。部分觀點可能會有誤導
本文要解決的問題: 對 RxJava 技術體系在 Android 實際項目中具體使用的理解

RxJava 理解

下面這段代碼對比與常規實現,很能說明 RxJava 的使用。(以下代碼來源于:給 Android 開發者的 RxJava 詳解 寫的很不錯,值得仔細閱讀)

使用 Thread 實現:

new Thread() {
    @Override
    public void run() {
        super.run();
        for (File folder : folders) {
            File[] files = folder.listFiles();
            for (File file : files) {
                if (file.getName().endsWith(".png")) {
                    final Bitmap bitmap = getBitmapFromFile(file);
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            imageCollectorView.addImage(bitmap);
                        }
                    });
                }
            }
        }
    }
}.start();

通過 RxJava 的使用:

Observable.from(folders)
    .flatMap(new Func1<File, Observable<File>>() {
        @Override
        public Observable<File> call(File file) {
            return Observable.from(file.listFiles());
        }
    })
    .filter(new Func1<File, Boolean>() {
        @Override
        public Boolean call(File file) {
            return file.getName().endsWith(".png");
        }
    })
    .map(new Func1<File, Bitmap>() {
        @Override
        public Bitmap call(File file) {
            return getBitmapFromFile(file);
        }
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Bitmap>() {
        @Override
        public void call(Bitmap bitmap) {
            imageCollectorView.addImage(bitmap);
        }
    });

這里可以看出,使用 RxJava 能夠很好的讓代碼邏輯變的簡單。RxJava 的操作方式乍一看很像 Builder 模式,在創建類的時候先給類添加各種初始化參數,然后調用 Build 創建對象。然而 RxJava 每一步都有相應的動作(action),既都會對上一個動作返回的數據做出必要的處理,然后將變化的數據傳遞下去。subscribe() 方法在末尾調用,最終數據會在這里被使用??梢哉J為 subscribe() 被調用后,就會啟動上面一連串動作(這樣理解對于初學者就夠)。
上面例子中用到的那些方法只要理解了,基本上 RxJava 就可以正常使用。有問題再查看官方文檔。

關于rxjava的一些記錄

Func1 和 Action1 的區別在于, Func1 包裝的是有返回值的方法。另外,和 ActionX 一樣, FuncX 也有多個,用于不同參數個數的方法。FuncX 和 ActionX的區別在 FuncX 包裝的是有返回值的方法。

線程控制

Observable.just(1,2,3,4) 
.subscribeOn(Schedulers.io()) 
.observeOn(Schedulers.newThread())
.map(doSomething) // 執行在 newThread 中
.observeOn(AndroidSchedulers.mainThread) 
.subscribe(subscriber); // 執行在 UI 線程中

observeOn()指定的是 Subscriber的線程,而這個 Subscriber并不是subscribe()參數中的 Subscriber,而是 observeOn()執行時的當前 Observable所對應的 Subscriber ,即它的直接下級 Subscriber 。換句話說,observeOn()指定的是它之后的操作所在的線程

Sqlbrite

簡介:A lightweight wrapper around SQLiteOpenHelper which introduces reactive stream semantics to SQL operations。個人覺得這是為了讓 SQLite 能和 RxJava 結合起來才有的庫
github 地址: sqlbrite

例子:

Observable<Query> users = db.createQuery("users", "SELECT * FROM users");
users.subscribe(new Action1<Query>() {
  @Override public void call(Query query) {
    Cursor cursor = query.run();
    // TODO parse data...
  }
});

因為作者的初衷并不是為了簡化對 SQLite 的操作,也沒有打算完全透明對 SQL 的使用。所以個人感覺不是很好用,我更樂意使用 GreenDao 。

Retrofit

一款現在很流行的網絡請求地方庫。使用起來很簡單。

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

另外關注以下幾個關鍵字:

  • @GET
  • @Path
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
  • @Query
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
  • @QueryMap
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
  • @Body

更多 API 用法可以查閱官方文檔 DOC ,也可搭配學習RxJava 與 Retrofit 結合的最佳實踐

EventBus 與 RxJava 的選擇

EventBus 官方介紹為:Android optimized event bus that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality. Detail

該庫的設計初衷是在 Activities, Fragments, Threads, Services 等模塊間輕松的建立鏈接。降低兩個模塊之間的耦合性,通過事件進行模塊間通信。同時支持異步操作。

RxJava 被設計出來的初衷也是為了解決異步任務。并且通過流式編寫,讓一連串任務依次執行。雖然 RxJava 是通過觀察者模式訂閱事件。但如果拋開被觀察者和觀察者的概念,通過代碼流式風格的編寫來理解 RxJava 設計思想,似乎也是可以的。

問題又回到了原點,EventBus 和 RxJava 該如何選擇呢?個人理解 RxJava 確實能從代碼的角度清晰業務邏輯。事件的處理有事件序列來控制,能很清楚展示一個事件從開始處理到結束所經歷的操作,并且可以根據需要控制事件在哪個 Thread 中被處理。當項目的業務很復雜的時候,我們會選擇將業務邏輯進行隔離。業務內部使用 RxJava 處理,業務之間可以通過 EventBus 來進行消息傳遞。這樣能使業務完全解耦。

RxJava 與 MVP

MVP 可以良好的將視圖層和數據層通過 Presenter 進行隔離。Google 開發者也給出了 MVP 相關的設計方案 android-architecture 可以從基本的 MVP 開始學習,然后過度到與 RxJava 集合。
大體思路是:

  • 編寫 Contract 接口存放 IView 接口和 Presenter 接口
public interface Contract {

    interface View extends BaseView<Presenter> {

        // 更新UI的操作接口
    }

    interface Presenter extends BasePresenter {

        // 業務相關數據操作接口
    }
}

public interface BasePresenter {

    void subscribe();

    void unsubscribe();

}

public interface BaseView<T> {

    void setPresenter(T presenter);

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

推薦閱讀更多精彩內容