使用RxAndroid處理異步任務(wù)

歡迎Follow我的GitHub, 關(guān)注我的簡(jiǎn)書(shū). 其余參考Android目錄.

Demo

本文的合集已經(jīng)編著成書(shū),高級(jí)Android開(kāi)發(fā)強(qiáng)化實(shí)戰(zhàn)细办,歡迎各位讀友的建議和指導(dǎo)雪隧。在京東即可購(gòu)買(mǎi):https://item.jd.com/12385680.html

Android

Rx是響應(yīng)式編程的意思, 本質(zhì)是觀察者模式, 是以觀察者(Observer)和訂閱者(Subscriber)為基礎(chǔ)的異步響應(yīng)方式. 在Android編程時(shí), 經(jīng)常會(huì)使用后臺(tái)線程, 那么就可以使用這種方式. 目前的異步編程方式都會(huì)導(dǎo)致一些問(wèn)題, 如

(1) Asynctasks can easily lead to memory leaks.
(2) CursorLoaders with a ContentProvider require a large amount of configuration and boilerplate code to setup.
(3) Services are intended for longer running background tasks and not fast-finishing operations, such as making a network call or loading content from a database.

RxAndroid來(lái)源于RxJava, 在RxJava的基礎(chǔ)上擴(kuò)展了一些Android的功能, 已經(jīng)發(fā)布1.0版本, 讓我們來(lái)看看怎么用吧.

本文源碼的GitHub下載地址

1. 準(zhǔn)備

新建一個(gè)HelloWorld程序. 配置build.gradle, 添加RxAndroid庫(kù)和Lamada表達(dá)式支持, 還有ButterKnife.

plugins {
    id "me.tatarka.retrolambda" version "3.2.2"
}
...

android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'io.reactivex:rxandroid:1.0.1'
}

Lambda表達(dá)式支持不是必須的, 可以讓你代碼更加簡(jiǎn)潔, 減少匿名類(lèi)的出現(xiàn).

2. 頁(yè)面

頁(yè)面很簡(jiǎn)單, 設(shè)置三個(gè)按鈕, 觸發(fā)耗時(shí)的線程操作, 分別用主線程, Asynctasks, Rx方式調(diào)用, 觀察ProcessBar的狀態(tài).

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <Button
        android:id="@+id/main_thread"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="主線程"/>

    <Button
        android:id="@+id/main_async"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/main_thread"
        android:layout_centerHorizontal="true"
        android:text="Asynctasks"/>

    <Button
        android:id="@+id/main_rx"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/main_async"
        android:layout_centerHorizontal="true"
        android:text="Rx"/>

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"/>

</RelativeLayout>

3. 邏輯

添加一個(gè)阻塞任務(wù), 執(zhí)行5秒, 成功反饋.

    // 長(zhǎng)時(shí)間運(yùn)行的任務(wù)
    private String longRunningOperation() {
        try {
            Thread.sleep(5000);
        } catch (Exception e) {
            Log.e("DEBUG", e.toString());
        }

        return "Complete!";
    }

主線程執(zhí)行時(shí), 會(huì)導(dǎo)致UI卡頓

        // 線程運(yùn)行
        mThreadButton.setOnClickListener(v -> {
            mThreadButton.setEnabled(false);
            longRunningOperation();
            Snackbar.make(mRootView, longRunningOperation(), Snackbar.LENGTH_LONG).show();
            mThreadButton.setEnabled(true);
        });

異步線程執(zhí)行

    // 異步線程
    private class MyAsyncTasks extends AsyncTask<Void, Void, String> {
        @Override
        protected void onPostExecute(String s) {
            Snackbar.make(mRootView, s, Snackbar.LENGTH_LONG).show();
            mAsyncButton.setEnabled(true);
        }

        @Override
        protected String doInBackground(Void... params) {
            return longRunningOperation();
        }
    }
        // 異步運(yùn)行
        mAsyncButton.setOnClickListener(v -> {
            mAsyncButton.setEnabled(false);
            new MyAsyncTasks().execute();
        });

響應(yīng)式方式執(zhí)行, 使用IO線程處理, 主線程響應(yīng), 也可以使用其他線程處理, 如Schedulers.io()處理IO的線程, Schedulers.computation()計(jì)算的線程, Schedulers.newThread()新創(chuàng)建的線程.

        // 使用IO線程處理, 主線程響應(yīng)
        Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext(longRunningOperation());
                subscriber.onCompleted();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());

        // 響應(yīng)式運(yùn)行
        mRxButton.setOnClickListener(v -> {
            mRxButton.setEnabled(false);
            observable.subscribe(new Subscriber<String>() {
                @Override
                public void onCompleted() {
                    mRxButton.setEnabled(true);
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(String s) {
                    Snackbar.make(mRootView, s, Snackbar.LENGTH_LONG).show();
                }
            });
        });

使用響應(yīng)式編程可以更好的處理內(nèi)存泄露問(wèn)題, 代碼也更加優(yōu)雅和可讀, 選擇執(zhí)行線程和監(jiān)聽(tīng)線程也更加方便. 在destroy時(shí), 可以關(guān)閉正在執(zhí)行的異步任務(wù). 還有一些其他優(yōu)勢(shì), 就參考網(wǎng)站吧.

OK, 使用響應(yīng)式這種好用的異步編程方式吧.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末这溅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子载迄,更是在濱河造成了極大的恐慌讯柔,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件护昧,死亡現(xiàn)場(chǎng)離奇詭異魂迄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)惋耙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)极祸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)慈格,“玉大人,你說(shuō)我怎么就攤上這事遥金≡±Γ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵稿械,是天一觀的道長(zhǎng)选泻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)美莫,這世上最難降的妖魔是什么页眯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮厢呵,結(jié)果婚禮上窝撵,老公的妹妹穿的比我還像新娘。我一直安慰自己襟铭,他們只是感情好碌奉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著寒砖,像睡著了一般赐劣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哩都,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天魁兼,我揣著相機(jī)與錄音,去河邊找鬼漠嵌。 笑死咐汞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的儒鹿。 我是一名探鬼主播化撕,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼挺身!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起锌仅,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤章钾,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后热芹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贱傀,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年伊脓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了府寒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魁衙。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖株搔,靈堂內(nèi)的尸體忽然破棺而出剖淀,到底是詐尸還是另有隱情,我是刑警寧澤纤房,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布纵隔,位于F島的核電站,受9級(jí)特大地震影響炮姨,放射性物質(zhì)發(fā)生泄漏捌刮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一舒岸、第九天 我趴在偏房一處隱蔽的房頂上張望绅作。 院中可真熱鬧,春花似錦蛾派、人聲如沸俄认。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)梭依。三九已至,卻和暖如春典尾,著一層夾襖步出監(jiān)牢的瞬間役拴,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工钾埂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留河闰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓褥紫,卻偏偏與公主長(zhǎng)得像姜性,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子髓考,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評(píng)論 25 707
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理部念,服務(wù)發(fā)現(xiàn),斷路器氨菇,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • 引言 RxAndroid是一個(gè)開(kāi)發(fā)庫(kù)、是一種代碼風(fēng)格豌研、也是一種思維方式妹田。 正如標(biāo)題所言唬党,RxAndroid的特點(diǎn)是...
    藍(lán)灰_q閱讀 24,765評(píng)論 4 106
  • .01. 米粒和芥末離婚了沮趣。 芥末出軌兩年屯烦,對(duì)象是一個(gè)坐臺(tái)小姐,這讓米粒那顆極強(qiáng)的自尊心受到了侮辱房铭。 更讓她炸毛的...
    草言閱讀 341評(píng)論 0 0
  • Git是一個(gè)開(kāi)源的分布式版本控制系統(tǒng)驻龟,用以有效、高速的處理從很小到非常大的項(xiàng)目版本管理缸匪。 安裝Git 1.方法一:...
    幻世神碼閱讀 245評(píng)論 0 0