前言:
作爲一個小菜鳥,以前都沒有用過RxJava,但這都絲毫不影響我在這裏BB。以前寫個異步就是new Thread()+new Handler();或者是使用new AsyncTask();來實現一個異步操作。大清早起來,就準備研究這個RxJava,想看看這個是個什麼玩意;
首先呢,學習一門新東西要先了解他,於是乎我就拿出我的看家本領“百度一下”;百度了一些文章,看着特別棒,講解的也很詳細,可是我TM就是不懂啊!
抱着“我的智商是沒有問題的”這一想法,我又細心的看了兩三遍,捋了捋思路,親自動手敲了下代碼,然後發現:
大佬們寫的東西總是站在大佬的角度出發的:哪怕是大佬已經想到了新手可能要比自己略遜一點,但大佬並沒有想到新手原來如此的笨(比如我),於是我在學的過程中就想寫一些小菜鳥們的入門寶典(從入門到放棄愛不釋手);
不多BB了,下面整點乾貨!
引入依賴:
不把庫引進來怎麼用!
·AndroidStudio的小夥伴們可以:
RxJava: compile 'io.reactivex:rxjava:1.0.14' compile 'io.reactivex:rxandroid:1.0.1' RxBinding: compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'//這個是另一個庫,先在這裏放着,初學不用理這個,引上邊兩個就可以了! |
換AndroidStudio吧! 鏈接: https://pan.baidu.com/s/14jRRvsTRZQjtc8KlZw0rZg 密碼: tyyh 買一贈一,順便還換個開發工具! |
多說一句,因爲我學的時候去GitHub看了一下,版本已經更新到了2.0,當時引入的是2.0的依賴,發現問題大了,好多方法都不一樣了,多了一些東西,看得我濛濛的;
我又重新引的1.x版本,初學者嘛,學會了1之後在延伸到2就容易很多了;除了RxJava之外,上面提到的RxBinding也是這樣,本身更新到了2.0版本,也是有一些方法發生了改變。我這裏引入的是一個0.4的版本;
庫引進來了,到了最關鍵的怎麼用了!你以爲我會直接上代碼?NoNoNo!先簡單介紹幾個有趣的概念,後面都會用的到的!
重要概念:
·響應式編程
RxJava 是一個響應式編程框架,採用觀察者設計模式。至於什麼事觀察者設計模式,可以自行百度; |
·Subscriber
觀察者,接受者,可接收Observable 、Subject 發射的數據,異步中就是再這裏接收數據並處理,一般最終會設置運行在ui線程; |
·Observable
被觀察者,發射源,數據處理和數據發送是在這裏進行的,這裏涵蓋了好多東西,包含線程,類型轉換,網絡請求等; |
·FuncX
RxJava中封裝的一個類,X代表的是參數個數;這個類用來指定有返回值的對象類型回調; |
·ActionX
作用和Func相同,只是這個類沒有返回值; |
·操作符
操作符有很多,指的是在進行響應式編程的過程中用到的一些工具方法,用來滿足各類需求;後面會介紹一些重要的操作符,其他的會附上一個連接自行研究; |
·Scheduler
線程控制。我們在使用RxJava時無可避免的就是爲了解決異步的問題,這個類爲我們提供了線程控制,如何在RxJava中自由的切換線程,就要看這個類的了; |
看到這裏是不是腦海裏多了幾個關鍵字?這幾個關鍵字在以後對RxJava的操作中是非常關鍵的;
代碼部分:
理解了概念了,就得上點硬貨了,不然光說不練可是假把式!
先從同步開始說起,就是我使用發送者發送一些數據,然後使用接受者收到之後在頁面顯示一下!就是這麼簡單!
頁面就不用貼出來了,文字描述一下就好了(一個Button,一個TextView) 在按鈕的監聽事件中,點擊按鈕發送數據 List<String> list = new ArrayList<>(); list.add("Hello!"); list.add("My name is HuJun!"); list.add("And you?"); list.add("How are you?"); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //第一種方法:使用create()創建一個Observable對象,並且執行相應的操作,發送一些數據到觀察者中; Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("hello1"); subscriber.onNext("hello2"); subscriber.onNext("hello3"); subscriber.onNext("hello4"); subscriber.onNext("hello5"); subscriber.onCompleted(); } }).subscribe(new Action1<String>() { @Override public void call(String s) { Log.d("TAG", "call: "); tv.append("\n"+s); } }); //第二種方法:from方法用於解析一個list,內置創建了一個被觀察者對象,並且把list中的每一個item //發送到了觀察者中,並且自動調用了onCompleted方法; Observable.from(list) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.d("TAG", "call: "); tv.append("\n"+s); } }); } }); 鏈接:Observable的創建 對於被觀察者的創建,根據應用的場景不同,RxJava給我們提供了許多方法,這裏就不一一贅述了,放個連接,可以瞭解一下,這部分也是我轉載的。 原文很長,被我拆分了一下,拆成了幾個短一點的文章; |
上述呢,就是RxJava最簡單的一個使用方式;你以爲這就結束了嗎?學完這個你會發現:然卵用???
我寫RxJava的最開始的意圖是爲了更好的實現異步操作,這個樣子那裏有半點異步的樣子了;
那我就來舉個異步的栗子算了;
舉例子之前,先說一下RxJava中關於異步的實現;
線程調度器--Scheduler中控制線程依賴一個Scheduler
對象,Scheduler
對象分爲一下幾類:
Schedulers.immediate() | 直接在當前線程中運行,相當於不指定線程,這也是RxJava默認的線程方式; |
Schedulers.newThread() | 啓用新線程,並且在新線程中執行操作; |
Schedulers.io() | I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的 Scheduler;區別在於 io() 的內部實現是是用一個無數量上限的線程池,可以重用空閒的線程,因此多數情況下 io() 比 newThread() 更有效率。 |
Schedulers.computation() | 計算所操作的線程,這個計算指的是CPU密集型計算; |
AndroidSchedulers.mainThread() | Android獨有的線程,就是所說的Android的主線程,UI線程; |
放下手中的刀,我這就舉個異步的例子:
代入一下場景: 小明要叫着小李出去打球,可是小李在洗澡,然後小明給小李發消息“我們一會去打球,看到了給我回個消息!”,然後小明就去看電視了,小李洗完澡之後看到消息之後,回消息給小明“完全ojbk!,我們這就走!”,小明收到回覆後關掉電視,一起去打球了; 分析一下的話,這個流程分爲:小明發出消息->等待小李看到->小李看到之後回覆->小明接收做操作; 在這個流程中,小明發出消息之後並沒有一直等着小李回覆,也就是並沒有阻塞主線程,而是接着就去看電視了從小明的角度來講,等待小李回消息就是在子線程中運行的,看電視則是運行在主線程; 這個問題用RxJava怎麼解決呢? final String xiaoming = "李哥去不去打籃球,看到回覆我一下,我先去看電視!"; Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext(xiaoming); doWatchTV();//執行看電視操作 subscriber.onCompleted(); } }) .subscribeOn(Schedulers.newThread()) .map(new Func1<String, String>() { @Override public String call(String s) { SystemClock.sleep(2000);//過了2000毫秒,小李收到消息 return s; } }) .observeOn(AndroidSchedulers.mainThread())//切換線程 .subscribe(new Action1<String>() { @Override public void call(String s) { //tv.setText("完全ojbk"); closeTV();//小明收到消息,關閉TV } }); 這看上去確實是一個毫無意義的功能,但是我們可以把他替換爲有意義的功能!比如網絡加載圖片等等; |
線程之間的轉換:
observeOn()
指定的是 Subscriber
的線程,而這個 Subscriber
並不是(嚴格說應該爲『不一定是』,但這裏不妨理解爲『不是』)subscribe()
參數中的 Subscriber
,而是 observeOn()
執行時的當前 Observable
所對應的 Subscriber
,即它的直接下級 Subscriber
。換句話說,observeOn()
指定的是它之後的操作所在的線程。因此如果有多次切換線程的需求,只要在每個想要切換線程的位置調用一次 observeOn()
即可。上代碼:
Observable.just(1, 2, 3, 4) // IO 線程,由 subscribeOn() 指定 .subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .map(mapOperator) // 新線程,由 observeOn() 指定 .observeOn(Schedulers.io()) .map(mapOperator2) // IO 線程,由 observeOn() 指定 .observeOn(AndroidSchedulers.mainThread) .subscribe(subscriber); // Android 主線程,由 observeOn() 指定 |
鏈接:RxJava操作符大全
看完這些呢,基本上剩下的關於RxJava的部分就要靠自己摸索了,有興趣也可以翻一翻源碼,看看是怎麼實現的,可能一開始看不懂,看多了就懂了;
文章結尾,再提一個東西,就是開頭也說道過的RxBinding;
都做過監聽的設置,看上邊的代碼不難發現setOnclickLinster的方法寫起來好像不是很美觀;
於是乎有了這麼一個框架,有了它之後,會讓你整個的代碼看上去就是很舒服的響應式的編碼佈局,看着就很爽;
使用方法也很簡單,我這裏舉個和RxJava一起用的栗子,更多例子老規矩也是賦個連接,自己去看;
RxBinding:
不多BB直接上代碼:RxView.clicks(findViewById(R.id.btn_iv)) .throttleFirst( 2 , TimeUnit.SECONDS )//設置兩秒內點擊無效 .subscribe(new Action1<Void>() { @Override public void call(Void aVoid) { Observable.just(urlstr) .map(new Func1<String, Object>() { @Override public Object call(String s) { SystemClock.sleep(2000); return null; } }) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Object>() { @Override public void call(Object object) { tv.setText("完全ojbk!"); Log.d(TAG, "call: object-------ok"); } }); } });這個栗子是響應了一個單擊事件,然後線程睡眠兩秒後通知ui線程更新數據; |
具體的多種用法我就把連接放到這裏了,可以去看看
:
鏈接:RxBinding使用
好了,到這裏就先這樣吧,我要去吃飯了,研究這東西研究了一下午了!
關於作者:
Name:賈恆飛
等級:菜雞
歡迎大佬們支援
QQ:2757525207
WX:jy271613
萌新來騷擾也是可以的;;;;妹子優先哦