Android拾萃 - RxJava實(shí)戰(zhàn)(后臺(tái)執(zhí)行耗時(shí)操作瞬逊,實(shí)時(shí)通知 UI 更新)

開源項(xiàng)目 RxJava-Android-Samples确镊,這里一共介紹了十八種RxJava2的使用場(chǎng)景,這一系列文章主要參考該項(xiàng)目進(jìn)行蕾域。

我們經(jīng)常會(huì)在后臺(tái)線程中去做一些耗時(shí)的操作旨巷,比如去網(wǎng)絡(luò)取數(shù)據(jù)采呐,處理的方法有
HandlerThread斧吐、Thread、Service煤率、IntentService洋只、AysncTask识虚、AsyncQueryHandler。對(duì)于它們的優(yōu)異舷礼,這里就不展開說(shuō)了妻献,戰(zhàn)友們自行Google吧~
當(dāng)獲取到數(shù)據(jù)育拨,更新UI頁(yè)面的時(shí)候熬丧,一般是不允許在其他線程直接操作的析蝴。下面我們來(lái)看下怎么在線程中操作UI界面闷畸。

方法一:Handler

子線程調(diào)用Handler的sendMessage(message)發(fā)送事件佑菩。

mHandler = new Handler() {  
   @Override  
   public void handleMessage(Message msg) {  
        //操作界面  
       myText.setText( 來(lái)自網(wǎng)絡(luò)的信息);  
      super.handleMessage(msg);  
   }  
  };  
 

public class MyThread extends Thread {  
     public void run() {  
?    ?    ?    // 耗時(shí)操作  
?    ?    ?    ?loadNetWork();  
            Message msg = new Message();  
            mHandler.sendMessage(msg);//向Handler發(fā)送消息殿漠,  
      }  
 }  

方法二:View.post(Runnable )

public void onClick( View v ) {  
        new Thread( new Runnable() {  
                public void run() {  
                       // 耗時(shí)操作  
?    ?    ?    ?    ?    ?      loadNetWork();  
?                          myText.( new Runnable() {  
                                  myText.setText( 來(lái)自網(wǎng)絡(luò)的信息);  
                          });  
                 }  
        }).start();  
}  

方法三:Activity.runOnUiThread(Runnable )

與view.post類似

public void onClick( View v ) {  
        new Thread( new Runnable() {  
                public void run() {  
                       // 耗時(shí)操作  
?    ?    ?    ?    ?    ?      loadNetWork();  
?                         Activity.runOnUiThread.( new Runnable() {  
                                  myText.setText( 來(lái)自網(wǎng)絡(luò)的信息);  
                          });  
                 }  
        }).start();  
}  

方法四:AsyncTask

//UI線程中執(zhí)行

new DownloadImageTask().execute( "www.linuxidc.com" );  
 
new DownloadImageTask().execute( "www.linuxidc.com" );  
 

private class LoadTask extends AsyncTask {  
    protected String doInBackground( String... url ) {  
         return loadDataFormNetwork( url[0] );//后臺(tái)耗時(shí)操作  
    }  
  
    protected void onPostExecute( String result ) {  
          myText.setText( result ); //得到來(lái)自網(wǎng)絡(luò)的信息刷新頁(yè)面   
  
   }  
private class LoadTask extends Anew DownloadImageTask().execute( "www.linuxidc.com" );  
 

private class LoadTask extends AsyncTask {  
    protected String doInBackground( String... url ) {  
         return loadDataFormNetwork( url[0] );//后臺(tái)耗時(shí)操作  
    }  
  
    protected void onPostExecute( String result ) {  
          myText.setText( result ); //得到來(lái)自網(wǎng)絡(luò)的信息刷新頁(yè)面   
  
   }  syncTask {  
    protected String doInBackground( String... url ) {  
         return loadDataFormNetwork( url[0] );//后臺(tái)耗時(shí)操作  
    }  
  
    protected void onPostExecute( String result ) {  
          myText.setText( result ); //得到來(lái)自網(wǎng)絡(luò)的信息刷新頁(yè)面   
  
   }  

RxJava 實(shí)現(xiàn)后臺(tái)執(zhí)行耗時(shí)操作一忱,實(shí)時(shí)通知 UI 更新

我們知道rxjava默認(rèn)的上下游是在同一個(gè)線程工作谭确,這樣明顯不能滿足我們的要求菇夸,這個(gè)時(shí)候我們就需要用到rxjava的線程調(diào)度了庄新。請(qǐng)參考
Android拾萃 - RxJava最簡(jiǎn)單的入門(一)
Android拾萃 - RxJava操作符列表和響應(yīng)類型(二)
Android拾萃 - RxJava操作符的使用(三)

public class BackgroundActivity extends AppCompatActivity {
    private TextView mTvDownload;
    private ProgressBar mProgressBar;
    private Disposable disposable;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_background);
        mTvDownload = (TextView) findViewById(R.id.start_download);
        mProgressBar = (ProgressBar) findViewById(R.id.progress);
        mProgressBar.setMax(100);
        mTvDownload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (disposable != null && !disposable.isDisposed()) {
                    Toast.makeText(BackgroundActivity.this, "已經(jīng)在下載中择诈,請(qǐng)稍后繼續(xù)羞芍。", Toast.LENGTH_SHORT).show();
                    return;
                }
                startDownload();
            }
        });

    }

    private void startDownload() {
        //Observable  對(duì)應(yīng)的上游類型是ObservableOnSubscribe 我們需要發(fā)射數(shù)據(jù)荷科,所以實(shí)現(xiàn)了ObservableEmitter方法
        Observable download = Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(@NonNull ObservableEmitter e) throws Exception {
                    for (int i=0; i<=100; i++){
                        if (i%10 == 0) {
                            try{
                                Thread.sleep(400);//模擬下載的操作
                            }catch (Exception e1) {
                                e1.printStackTrace();
                                if (!e.isDisposed()) {
                                    e.onError(e1);
                                }
                            }
                            if ((disposable != null && !disposable.isDisposed()) || disposable == null)
                                e.onNext(i);
                        }
                    }
                    e.onComplete();
            }
        });

        //方式一
        //Observable 對(duì)應(yīng)的下游類型是Observer
        Observer observer = new Observer() {
            //rx2 新加入的方法,在訂閱后發(fā)送數(shù)據(jù)之前狞贱,
            //回首先調(diào)用這個(gè)方法蝎毡,而Disposable可用于取消訂閱
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                disposable = d;
            }

            @Override
            public void onNext(@NonNull Object o) {
                mProgressBar.setProgress((Integer) o);
            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {
                Toast.makeText(BackgroundActivity.this, " 下載完成沐兵!", Toast.LENGTH_SHORT).show();
                if (disposable != null && !disposable.isDisposed()) {
                    disposable.dispose();
                    disposable = null;
                }

            }
        };

        //建立訂閱關(guān)系
        download.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);//把這段代碼連起來(lái)寫就成了RxJava引以為傲的鏈?zhǔn)讲僮?
        
        //方式二
        
        //Observable 對(duì)應(yīng)的下游類型是Consumer
        Consumer consumer = new Consumer<Integer>() {

            @Override
            public void accept(Integer integer) throws Exception {
                mProgressBar.setProgress((Integer) integer);
            }
        };

        //建立訂閱關(guān)系
//        download.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(consumer);//把這段代碼連起來(lái)寫就成了RxJava引以為傲的鏈?zhǔn)讲僮?

    }
}
device-2017-09-10-025027.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市便监,隨后出現(xiàn)的幾起案子痒筒,更是在濱河造成了極大的恐慌,老刑警劉巖茬贵,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件簿透,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡解藻,警方通過(guò)查閱死者的電腦和手機(jī)老充,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)螟左,“玉大人啡浊,你說(shuō)我怎么就攤上這事〈龋” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵思喊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)诬留,這世上最難降的妖魔是什么腺劣? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任拒名,我火速辦了婚禮,結(jié)果婚禮上糖权,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好释液,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布寝蹈。 她就那樣靜靜地躺著,像睡著了一般阔籽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天寇窑,我揣著相機(jī)與錄音,去河邊找鬼熟掂。 笑死誉券,一個(gè)胖子當(dāng)著我的面吹牛商玫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼细睡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涕滋,失蹤者是張志新(化名)和其女友劉穎侵俗,沒(méi)想到半個(gè)月后洪橘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卿城,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年星掰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了怀偷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡畴栖,死狀恐怖沸停,靈堂內(nèi)的尸體忽然破棺而出伙菊,到底是詐尸還是另有隱情运翼,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布兴枯,位于F島的核電站血淌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏财剖。R本人自食惡果不足惜悠夯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望峰伙。 院中可真熱鬧疗疟,春花似錦、人聲如沸瞳氓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至店诗,卻和暖如春裹刮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庞瘸。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工捧弃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人擦囊。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓违霞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親瞬场。 傳聞我的和親對(duì)象是個(gè)殘疾皇子买鸽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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