介紹
a library for composing asynchronous and event-based programs using observable sequences for the Java VM -------一個在 Java VM 上使用可觀測的序列來組成異步的、基于事件的程序的庫
使用
1、關聯
compile 'io.reactivex:rxjava:1.0.14'
compile 'io.reactivex:rxandroid:1.0.1'
2、簡單示例
public void test01(){
? ? ? ? Log.e(tag,"------------test01-----------" +
? ? ? ? ? ? ? ? "\n----------簡單實例01---------");
? ? ? ? //創建被觀察者
? ? ? ? Observable observable = Observable.create(new Observable.OnSubscribe() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Subscriber subscriber) {
? ? ? ? ? ? ? ? //調用觀察者的回調
? ? ? ? ? ? ? ? subscriber.onNext("我是");
? ? ? ? ? ? ? ? subscriber.onNext("RxJava");
? ? ? ? ? ? ? ? subscriber.onNext("簡單示例");
? ? ? ? ? ? ? ? subscriber.onError(new Throwable("出錯了"));
? ? ? ? ? ? ? ? subscriber.onCompleted();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? //創建觀察者
? ? ? ? Observer observer = new Observer() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onCompleted() {
? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onError(Throwable e) {
? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onNext(String s) {
? ? ? ? ? ? ? ? Log.e(tag,s);
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? //注冊,是的觀察者和被觀察者關聯,將會觸發OnSubscribe.call方法
? ? ? ? observable.subscribe(observer);
? ? }
運行結果:
? ? =====>: ------------test01-----------
? ? ? ? ? ? ----------簡單實例01---------
? ? =====>: 我是
? ? =====>: RxJava
? ? =====>: 簡單示例
? ? =====>: 出錯了
Observable是被觀察者,通過create創建(還有其他方式,后面將會講到),傳入一個OnSubscribe對象,當Observable調用subscribe進行注冊觀察者時,OnSubscribe的call方法會觸發。Observer是觀察者,他有三個回調方法:
onNext? ? ? :接受到一個事件
onCompleted :接受完事件后調用,只會調用一次
onError? ? :發生錯誤時調用,并停止接受事件,調用一次
onCompleted和onError不會同時調用,只會調用其中之一
觀察者除了使用Observer,還可以使用Subscriber,它跟?Observer作用一樣,如下:
public void test02(){
? ? ? ? Log.e(tag,"------------test02-----------" +
? ? ? ? ? ? ? ? "\n----------簡單實例02---------");
? ? ? ? //創建被觀察者
? ? ? ? Observable observable = Observable.create(new Observable.OnSubscribe() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Subscriber subscriber) {
? ? ? ? ? ? ? ? //調用觀察者的回調
? ? ? ? ? ? ? ? subscriber.onNext("我是");
? ? ? ? ? ? ? ? subscriber.onNext("RxJava");
? ? ? ? ? ? ? ? subscriber.onNext("簡單示例");
? ? ? ? ? ? ? ? subscriber.onCompleted();
? ? ? ? ? ? ? ? subscriber.onError(new Throwable("出錯了"));
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? //創建觀察者
? ? ? ? Subscriber subscriber = new Subscriber() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onStart() {
? ? ? ? ? ? ? ? Log.e(tag,"onStart");
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onCompleted() {
? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onError(Throwable e) {
? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onNext(String s) {
? ? ? ? ? ? ? ? Log.e(tag,s);
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? //注冊,使得觀察者和被觀察者關聯,將會觸發OnSubscribe.call方法
? ? ? ? observable.subscribe(subscriber);
? ? }
運行結果
=====>: ------------test02-----------
? ? ? ? ----------簡單實例02---------
=====>: onStart
=====>: 我是
=====>: RxJava
=====>: 簡單示例
=====>: onCompleted
這里只是多了一個onStart方法 ,這個方法會在Observable調用方法subscribe注冊觀察者時調用一次,表明事件要開始了。
因為Subscriber只是對Observer的擴展,用法都一樣,所以后面例子都用?Subscriber做觀察者。
3、Observable的創建
前面簡單的例子中,創建Observable是通過create方法,當然還有其他方法,體驗一下吧:
public void test03(){
? ? ? ? Log.e(tag,"------------test03-----------" +
? ? ? ? ? ? ? ? "\n----------創建觀察者01---------");
? ? ? ? Integer[] ints={1,2,3,4};
? ? ? ? Observable.from(ints).subscribe(new Subscriber() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onCompleted() {
? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onError(Throwable e) {
? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onNext(Integer integer) {
? ? ? ? ? ? ? ? Log.e(tag,integer+"");
? ? ? ? ? ? }
? ? ? ? });
? ? }
運行結果
=====>: ------------test03-----------
? ? ? ? ----------創建觀察者01---------
=====>: 1
=====>: 2
=====>: 3
=====>: 4
=====>: onCompleted
from方法將傳入的數組或 Iterable 拆分成具體對象后,依次發送出來。
public void test04(){
? ? ? ? Log.e(tag,"------------test04-----------" +
? ? ? ? ? ? ? ? "\n----------創建被觀察者02---------");
? ? ? ? Observable.just(1,2,3,4).subscribe(new Subscriber() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onCompleted() {
? ? ? ? ? ? ? ? Log.e(tag,"onCompleted");
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onError(Throwable e) {
? ? ? ? ? ? ? ? Log.e(tag,e.getMessage());
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onNext(Integer integer) {
? ? ? ? ? ? ? ? Log.e(tag,integer+"");
? ? ? ? ? ? }
? ? ? ? });
? ? }
運行結果
=====>: ------------test04-----------
? ? ? ? ----------創建被觀察者02---------
=====>: 1
=====>: 2
=====>: 3
=====>: 4
=====>: onCompleted
和from方法一樣,just(T...): 將傳入的參數依次發送出來。
4、觀察者的其他可用形式
觀察者Subscriber和Observer都需要寫三個回調,有時候我們只關系其中一個回調,或者兩個
public void test05(){
? ? ? ? Log.e(tag,"------------test05-----------" +
? ? ? ? ? ? ? ? "\n----------創建觀察者其他形式---------");
? ? ? ? String[] strs={"aa","bb","cc"};
? ? ? ? Action1 onNextAction = new Action1() {
? ? ? ? ? ? // onNext()
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(String s) {
? ? ? ? ? ? ? ? Log.d(tag, s);
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? Action1 onErrorAction = new Action1() {
? ? ? ? ? ? // onError()
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Throwable throwable) {
? ? ? ? ? ? ? Log.e(tag,throwable.getMessage());
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? Action0 onCompletedAction = new Action0() {
? ? ? ? ? ? // onCompleted()
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call() {
? ? ? ? ? ? ? ? Log.d(tag, "completed");
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? Observable observable = Observable.from(strs);
? ? ? ? // 自動創建 Subscriber ,并使用 onNextAction 來定義 onNext()
? ? ? ? observable.subscribe(onNextAction);
? ? ? ? // 自動創建 Subscriber ,并使用 onNextAction 和 onErrorAction 來定義 onNext() 和 onError()
? ? ? ? observable.subscribe(onNextAction, onErrorAction);
? ? ? // 自動創建 Subscriber ,并使用 onNextAction、 onErrorAction 和 onCompletedAction 來定義 onNext()、 onError() 和 onCompleted()
? ? ? ? observable.subscribe(onNextAction, onErrorAction, onCompletedAction);
? ? }
這里使用了Action1和Action0, Action0 是 RxJava 的一個接口,它只有一個方法 call(),這個方法是無參無返回值的;由于 onCompleted() 方法也是無參無返回值的,因此 Action0 可以被當成一個包裝對象,將 onCompleted() 的內容打包起來將自己作為一個參數傳入 subscribe() 以實現不完整定義的回調。 Action1 也是一個接口,它同樣只有一個方法 call(T param),這個方法也無返回值,但有一個參數;與 Action0 同理,由于 onNext(T obj) 和 onError(Throwable error) 也是單參數無返回值的,因此 Action1 可以將 onNext(obj) 和 onError(error) 打包起來傳入 subscribe() 以實現不完整定義的回調。事實上,雖然 Action0 和 Action1 在 API 中使用最廣泛,但 RxJava 是提供了多個 ActionX 形式的接口 (例如 Action2, Action3) 的,它們可以被用以包裝不同的無返回值的方法。
5、線程調度
RxJava遵循線程不變原則,在不做特殊處理的情況下,在哪個線程調用 subscribe(),就在哪個線程生產事件;在哪個線程生產事件,就在哪個線程消費事件。如果需要切換線程,就需要用到 Scheduler (調度器)
? ? public void test06(){
? ? ? ? Log.e(tag, "------------test06-----------" +
? ? ? ? ? ? ? ? "\n----------線程調度---------");
? ? ? ? //從網絡上根據用戶id,請求對應用戶,并顯示用戶積分到界面
? ? ? ? Observable.create(new Observable.OnSubscribe() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Subscriber subscriber) {
? ? ? ? ? ? ? ? int id=111;
? ? ? ? ? ? ? ? UserInfo userinfo=getUserInfoFromNet(id);
? ? ? ? ? ? ? ? subscriber.onNext(userinfo.points);
? ? ? ? ? ? }
? ? ? ? }).subscribeOn(Schedulers.io())//事件產生在io線程
? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())//消耗事件在主線程
? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? public void call(Integer points) {
? ? ? ? ? ? ? ? ? Log.e(tag, "顯示用戶積分:" + points);
? ? ? ? ? ? ? }
? ? ? ? ? });
? ? }
? ? //模擬從網絡請求
? ? private UserInfo getUserInfoFromNet(int id) {
? ? ? ? UserInfo userInfo = new UserInfo();
? ? ? ? userInfo.points=100;
? ? ? ? return userInfo;
? ? }
? ? public class UserInfo{
? ? ? ? public int id;
? ? ? ? public int points;
? ? }
運行結果
=====>: ------------test06-----------
? ? ? ? ----------線程調度---------
=====>: 顯示用戶積分:100
在io線程中根據id請求用戶信息,在主線程中將用戶積分顯示到界面
Schedulers.newThread(): 總是啟用新線程,并在新線程執行操作,適用于復雜計算。
Schedulers.io(): I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)
AndroidSchedulers.mainThread(),它指定的操作將在 Android 主線程運行
subscribeOn(): 指定 subscribe() 所發生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產生的線程。
observeOn(): 指定 Subscriber 所運行在的線程。或者叫做事件消費的線程
6、變換
舉一個例子:通過用戶id,從數據庫中請求用戶名稱,只需要名稱就行,id是int類型,用戶名稱是string類型
public void test07(){
? ? ? ? Log.e(tag, "------------test07-----------" +
? ? ? ? ? ? ? ? "\n----------變換01---------");
? ? ? ? //從數據庫中根據id獲取用戶名稱
? ? ? ? Observable.just(111)
? ? ? ? ? ? ? ? .map(new Func1() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public String call(Integer id) {
? ? ? ? ? ? ? ? ? ? ? ? return getNameFromDb(id);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call(String s) {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(tag,s);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? }
? ? //模擬從數據獲取信息
? ? private String getNameFromDb(int id){
? ? ? ? return "username";
? ? }
? ? public class UserInfo{
? ? ? ? public int id;
? ? ? ? public String name;
? ? ? ? public int points;
? ? }
運行結果
=====>: ------------test07-----------
? ? ? ? ----------變換01---------
=====>: username
這里的map有轉換的作用,這里是吧Observable轉換成了Observable,事件只能是一對一的轉換,把發射id的事件,轉換成了發射username的事件
flatmap轉換,舉一個例子:根據id從數據庫中獲取指定用戶的愛好,并打印出來
public void test08(){
? ? ? ? Log.e(tag, "------------test08-----------" +
? ? ? ? ? ? ? ? "\n----------變換02---------");
? ? ? ? Observable.just(111)
? ? ? ? ? ? ? ? .flatMap(new Func1>() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public Observable call(Integer id) {
? ? ? ? ? ? ? ? ? ? ? ? return Observable.from(getHobbies(id));
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call(String s) {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(tag,s);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? }
? ? //模擬從數據獲取信息
? ? private String[] getHobbies(int id){
? ? ? ? return new String[]{"singing","running","shopping"};
? ? }
? ? public class UserInfo{
? ? ? ? public int id;
? ? ? ? public String name;
? ? ? ? public int points;
? ? ? ? public String[] hobbies;
? ? }
運行結果
=====>: ------------test08-----------
? ? ? ? ----------變換02---------
=====>: singing
=====>: running
=====>: shopping
這里將Observable轉換成了?Observable.from(getHobbies(id)),將發射id的事件,轉換成了多個發射愛好的事件(愛好有多個),事件是一對多
7、反注冊
rxJava是基于觀察者模式的,我們知道觀察者模式中有注冊和反注冊,反注冊就是為了釋放資源,防止內存泄露,rxjava中也是,我們也需要及時反注冊并釋放資源,
? ? private Subscription subscription;
? ? public void test09(){
? ? ? ? Log.e(tag, "------------test09-----------" +
? ? ? ? ? ? ? ? "\n----------反注冊---------");
? ? ? ? subscription = Observable.create(new Observable.OnSubscribe() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void call(Subscriber subscriber) {
? ? ? ? ? ? ? ? ? ? SystemClock.sleep(5000);\\暫停5秒鐘
? ? ? ? ? ? ? ? ? ? subscriber.onNext("hahaha");
? ? ? ? ? ? ? ? ? ? subscriber.onCompleted();\\標志事件發送完畢,just和from會自動調用onCompleted
? ? ? ? ? ? ? ? }
? ? ? ? ? ? })
? ? ? ? ? ? .subscribeOn(Schedulers.newThread())
? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())
? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(String s) {
? ? ? ? ? ? ? ? Log.e(tag, s);
? ? ? ? ? ? }
? ? ? ? });
? ? }
? ? @Override
? ? protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? Log.e(tag,"是否已經反注冊:"+subscription.isUnsubscribed()+"");
? ? ? ? //先判斷是否已經反注冊
? ? ? ? if(!subscription.isUnsubscribed()){
? ? ? ? ? ? Log.e(tag,"進行反注冊");
? ? ? ? ? ? subscription.unsubscribe();
? ? ? ? ? ? Log.e(tag,"是否已經反注冊:"+subscription.isUnsubscribed()+"");
? ? ? ? }
? ? }
Subscription是注冊關系,Observable調用subscribe方法時,會形成一個注冊關系,Subscription的isUnsubscribed()方法來判斷是否已經反注冊,unsubscribe()方法來進行反注冊。一般情況下,當事件發送完成后,觀察者會自動反注冊,不用我們調用Subscription的unsubscribe()方法進行反注冊,但是當有耗時操作時,我們就有必要進行反注冊,上面代碼的運行結果如下:
運行結果
在事件還沒有發送完畢時(5秒之內),我們關閉了activity:
=====>: ------------test09-----------
? ? ? ? ----------反注冊---------
=====>: 是否已經反注冊:false
=====>: 進行反注冊
=====>: 是否已經反注冊:true
事件已經發送完(5秒之后),我們關閉activity:
=====>: ------------test09-----------
? ? ? ? ----------反注冊---------
=====>: hahaha
=====>: 是否已經反注冊:true
8、操作符使用
rxJava有著豐富的操作符,來對數據進行流式的操作處理,上面講到的map和flatmap就是rxJava的操作符,由于操作符太多,只示范常用的幾個:
public void test10(){
? ? Log.e(tag, "------------test10-----------" +
? ? ? ? ? ? "\n----------操作符---------");
? String[] strs={"aa","bb","bb","cc","dd","ee"};
? ? Observable observable = Observable.from(strs);
? ? //filter(Func1)方法來過濾我們觀測序列中不想要的值
? ? //take(count)方法來限制獲取多少個數據
? ? Log.e(tag,"---------filter & take----------");
? ? observable
? ? ? ? ? ? .filter(new Func1() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public Boolean call(String s) {
? ? ? ? ? ? ? ? ? ? //把已b結尾的數據去掉
? ? ? ? ? ? ? ? ? ? return !s.endsWith("b");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? })
? ? ? ? ? ? .take(3)//取3個數據
? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void call(String s) {
? ? ? ? ? ? ? ? ? ? Log.e(tag,s);
? ? ? ? ? ? ? ? }
? ? ? ? });
? ? Log.e(tag,"---------skip & first----------");
? ? observable
? ? ? ? ? ? .skip(3)
? ? ? ? ? ? .first()
? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void call(String s) {
? ? ? ? ? ? ? ? ? ? Log.e(tag,s);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
}
運行結果
=====>: ------------test10-----------
? ? ? ? ----------操作符---------
=====>: ---------filter & take----------
=====>: aa
=====>: cc
=====>: dd
=====>: ---------skip & first----------
=====>: cc
類似的這種簡單的操作符還有:
last() 取最后一個
distinct() 去除重復的
skipLast() 去除最后一個
takeLast(count) 取最后count個
limit(count) 限制個數
doOnNext(Action1) 允許我們在每次輸出一個元素之前做一些額外的事情,比如保存起來。
還有好多,這只是簡單的介紹一下,在RxJava操作符專題中有詳解
9、RxLifecycle
我們上面提到了反注冊來防止內存泄露,但是反注冊需要我們自己動手寫,而使用Rxlifecycle就可以幫助我們將反注冊綁定到activity或者fragment的生命周期中,在他們的生命周期中自動去解綁。
使用方法
添加依賴,有最新的依賴,但是下面的比較穩定編譯也能通過
compile 'com.trello:rxlifecycle:0.3.1'
compile 'com.trello:rxlifecycle-components:0.3.1'
Activity/Fragment需繼承RxAppCompatActivity/RxFragment,目前支持的有RxAppCompatActivity、RxFragment、RxDialogFragment、RxFragmentActivity
綁定生命周期的時候可調用的方法:
bindToLifecycle()
bindUntilEvent()
例子
public class MainActivity extends RxAppCompatActivity {
? ? private static final String TAG = "=====>";
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? Log.e(TAG, "onCreate()");
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? Observable.interval(1, TimeUnit.SECONDS)
? ? ? ? ? ? ? ? .doOnUnsubscribe(new Action0() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call() {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Unsubscribing subscription from onCreate()");
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .compose(this.bindUntilEvent(ActivityEvent.PAUSE))
? ? ? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call(Long num) {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Started in onCreate(), running until onPause(): " + num);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? }
? ? @Override
? ? protected void onStart() {
? ? ? ? super.onStart();
? ? ? ? Log.e(TAG, "onStart()");
? ? ? ? // Using automatic unsubscription, this should determine that the correct time to
? ? ? ? // unsubscribe is onStop (the opposite of onStart).
? ? ? ? Observable.interval(1, TimeUnit.SECONDS)
? ? ? ? ? ? ? ? .doOnUnsubscribe(new Action0() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call() {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Unsubscribing subscription from onStart()");
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .compose(this.bindToLifecycle())
? ? ? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call(Long num) {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Started in onStart(), running until in onStop(): " + num);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? }
? ? @Override
? ? protected void onResume() {
? ? ? ? super.onResume();
? ? ? ? Log.e(TAG, "onResume()");
? ? ? ? // `this.` is necessary if you're compiling on JDK7 or below.
? ? ? ? //
? ? ? ? // If you're using JDK8+, then you can safely remove it.
? ? ? ? Observable.interval(1, TimeUnit.SECONDS)
? ? ? ? ? ? ? ? .doOnUnsubscribe(new Action0() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call() {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Unsubscribing subscription from onResume()");
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .compose(this.bindUntilEvent(ActivityEvent.DESTROY))
? ? ? ? ? ? ? ? .subscribe(new Action1() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call(Long num) {
? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG, "Started in onResume(), running until in onDestroy(): " + num);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? }
? ? @Override
? ? protected void onPause() {
? ? ? ? super.onPause();
? ? ? ? Log.e(TAG, "onPause()");
? ? }
? ? @Override
? ? protected void onStop() {
? ? ? ? super.onStop();
? ? ? ? Log.e(TAG, "onStop()");
? ? }
? ? @Override
? ? protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? Log.e(TAG, "onDestroy()");
? ? }
}
打開activity,兩秒后關閉,這樣每一個Observable發送兩個事件
運行結果
=====>: onCreate()
=====>: onStart()
=====>: onResume()
=====>: Started in onCreate(), running until onPause(): 0
=====>: Started in onStart(), running until in onStop(): 0
=====>: Started in onResume(), running until in onDestroy(): 0
=====>: Started in onCreate(), running until onPause(): 1
=====>: Started in onStart(), running until in onStop(): 1
=====>: Started in onResume(), running until in onDestroy(): 1
=====>: Unsubscribing subscription from onCreate()
=====>: onPause()
=====>: Unsubscribing subscription from onStart()
=====>: onStop()
=====>: Unsubscribing subscription from onResume()
關閉activity后,可以看出每一個Observable對應的注冊者在相應的生命周期函數中反注冊。?bindUntilEvent()方法需要傳入要綁定的生命周期。使用ActivityEvent類,其中的CREATE、START、 RESUME、PAUSE、STOP、 DESTROY分別對應生命周期內的方法。使用bindUntilEvent指定在哪個生命周期方法調用時取消訂閱
bindToLifecycle()方法完成Observable發布的事件和當前的組件綁定,實現生命周期同步。從而實現當前組件生命周期結束時,自動取消對Observable訂閱。
10、RxBinding
RxBinding是Rx中處理控件異步調用的方式, 也是由Square公司開發, Jake負責編寫. 通過綁定組件, 異步獲取事件, 并進行處理。
使用
關聯
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
compile 'com.jakewharton.rxbinding:rxbinding-support-v4:0.4.0'
實例
? ? 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"
? ? android:orientation="vertical"
? ? tools:context="cn.domob.android.rxjava_android.MainActivity">
? ? ? ? android:id="@+id/tv_main"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="Hello World!" />
? ? ? ? android:id="@+id/bt_main_01"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="改變字體顏色"/>
? ? ? ? android:id="@+id/bt_main_02"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:text="長按彈toast"/>
? ? ? ? android:id="@+id/et_main"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:hint="搜索"/>
? ? ? ? android:id="@+id/lv_main"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="match_parent"/>
public class MainActivity extends RxAppCompatActivity {
? ? private static final String TAG = "=====>";
? ? @InjectView(R.id.tv_main)
? ? TextView tv;
? ? @InjectView(R.id.bt_main_01)
? ? Button bt01;
? ? @InjectView(R.id.bt_main_02)
? ? Button bt02;
? ? @InjectView(R.id.et_main)
? ? EditText et;
? ? @InjectView(R.id.lv_main)
? ? ListView lv;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? ButterKnife.inject(this);
? ? ? ? //單機事件
? ? ? ? RxView.clicks(bt01).subscribe(new Action1() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Void aVoid) {
? ? ? ? ? ? ? ? tv.setTextColor(Color.parseColor("#ff0000"));
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? //長按事件
? ? ? ? RxView.longClicks(bt02).subscribe(new Action1() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Void aVoid) {
? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this, "hahha", Toast.LENGTH_SHORT).show();? ?
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? //防止連續點擊
? ? ? ? RxView.clicks(bt02).throttleFirst(5, TimeUnit.SECONDS).subscribe(new Action1() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Void aVoid) {
? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this, "防止多次連續點擊", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? //完成關鍵詞聯想功能,debounce()在一定的時間內沒有操作就會發送事件,顯示關鍵詞
? ? ? ? final ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_expandable_list_item_1);
? ? ? ? lv.setAdapter(adapter);
? ? ? ? RxTextView.textChanges(et)
? ? ? ? ? ? ? ? .debounce(600,TimeUnit.MILLISECONDS)
? ? ? ? ? ? ? ? .map(new Func1() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public String call(CharSequence charSequence) {
? ? ? ? ? ? ? ? ? ? ? ? return charSequence.toString();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .map(new Func1>() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public List call(String key) {
? ? ? ? ? ? ? ? ? ? ? ? ArrayList arrayList = new ArrayList<>();
? ? ? ? ? ? ? ? ? ? ? ? if(!TextUtils.isEmpty(key)){
? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int i = 0; i < getdata().size(); i++) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(getdata().get(i).contains(key))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? arrayList.add(getdata().get(i));
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? return arrayList;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())
? ? ? ? ? ? ? ? .subscribe(new Action1>() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void call(List strings) {
? ? ? ? ? ? ? ? ? ? ? ? adapter.clear();
? ? ? ? ? ? ? ? ? ? ? ? adapter.addAll(strings);
? ? ? ? ? ? ? ? ? ? ? ? adapter.notifyDataSetChanged();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? });
? ? ? ? RxAdapterView.itemClicks(lv).subscribe(new Action1() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void call(Integer integer) {
? ? ? ? ? ? ? ? et.setText(adapter.getItem(integer));
? ? ? ? ? ? }
? ? ? ? });
? ? }
? ? public List getdata(){
? ? ? ? return Arrays.asList("abc","abddfds","123","124567","1278934","adfghjl","!@#45d","響應式編程");
? ? }
}