作者:hwj3747
轉載請注明
目錄
- (1)配置篇
- (2)Lambda表達式
- (3)icepick篇
- (4)butterknife篇
- (5)MVP篇
- (6)Retrofit篇
- (7)Dagger2篇
- (8)RxAndroid/RxJava篇
RxJava介紹
首先要說明的一點,RxAndroid和RxJava是差不多的東西,隻不過RxAndroid 針對Android平台做了一點調整。那麼RxJava是什麼?在其github上是這樣講的:一個在 Java VM 上使用可觀測的序列來組成異步的、基于事件的程式的庫。這麼講可能還有點繞口,簡單的講實際上最重要的就是異步兩字,RxJava可以簡單的實作異步操作,并且不管邏輯多麼複雜,它始終能夠保持簡潔性。
通常在Android中,非UI線程是不能更新UI界面的,而一些耗時的操作我們又不能放在UI線程,否則會導緻界面卡頓。這種情況下,我們就需要切換線程來實作,即Handler和AsyncTask來實作,但是這兩種都有個缺陷,代碼非常多,非常雜,可讀性非常差。是以,RxJava出現了,它能夠兩行代碼就實作線程切換,非常的簡單,使用起來就會讓人感覺很爽,再也不用為異步操作寫如此繁重的代碼了。
RxJava基本用法
RxJava最核心的兩個東西是Observables(被觀察者,事件源)和Observer/Subscriber(觀察者),還有将他們聯系在一起的操作subscribe(訂閱)。當被觀察者發生變化時觀察者能即使做出相應,就好像我們的按鈕事件一樣:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
在這裡button就是被觀察者,OnClickListener就是觀察者,setOnClickListener這個方法就相當于訂閱操作,當button被按下時,OnClickListener監聽到變化,調用OnClick做出反應,RxJava實作的就是類似這樣的一個過程。注意這裡的觀察者有兩種Observer,Subscriber,這兩個其實是差不多的,Subscriber是對Observer的一種擴充,内部增加了OnStart方法,在事件未發送之前訂閱,用于做一些準備工作,并且還有unsubscribe()用于取消訂閱。
讓我們來看一下ObServer的内部實作:
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
可以看到ObServer本身是一個接口,内部有onNext(T t)方法:觀測到所檢測的被觀察者有變化時做出相應反應。onCompleted()方法:RxJava 規定,當不會再有新的 onNext() 發出時,需要觸發 onCompleted() 方法作為标志。onCompleted():事件隊列發生異常,要調用的方法。我們在定義一個觀察者的時候,需要實作這些方法,來完成事件隊列。
觀察者有了,那麼被觀察者Observables怎麼建立呢,RxJava提供了一系列操作符供我們調用,其中就有很多建立型操作符,舉個例子,建立一個Observables,發出hello world字元串給觀察者:
Observable<String> myObservable = Observable.create(
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> sub) {
sub.onNext("Hello, world!");
sub.onCompleted();
}
}
);
既然有了Observables,那我們就可以根據這個Observables建立一個觀察者了,如下:
Observer<String> TestObserver=new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.i(TAG,s);
}
}
這樣我們就可以愉快的訂閱了:
myObservable.subscribe(TestObserver);
這樣,一個簡單的RxJava訂閱流程就完成了。這裡可能很多人就有疑問了,關鍵的異步呢,展現在哪了?其實這個例子可能不是很明顯,因為被觀察者并不是一個耗時線程,不能很直覺的展現異步。如果myObservable這是一個異步任務,比如網絡請求,那麼我們訂閱之後,TestObserver會一直監聽myObservable是否有傳回,如果有,那麼就做出響應,本質是一樣的。
###RxJava的操作符
RxJava一個強大的地方在于它的異步,另外一個強大的地方就在于它提供了強大的操作符支援。這裡說明一下幾個常用的操作符:
- ceate操作符
Observable<String> myObservable = Observable.create(
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> sub) {
sub.onNext("Hello, world!");
sub.onCompleted();
}
}
);
ceate操作符建立一個被觀察者,在call方法裡持有一個觀察者Subscriber參數,當這個Observable被訂閱時,執行觀察者相應的方法。
- just操作符
Observable<String> myObservable = Observable.just("Hello, world!");
上面的代碼可以用這一句話,代替。just操作符的功能就是将一個對象轉化為Observable。
- from操作符
Observable<String> myObservable = Observable.from("Hello"," world!");
既然有了将單一對象轉化為Observable的操作符,那麼必須要有将多個對象轉化為Observable的操作符,那就是from,from接收一個對象數組,然後逐一發射給觀察者。
現在,用一個例子來說明其他操作符,比如我們有這樣一個方法,根據學生姓名關鍵字查詢學生清單,傳回一個Observable。
Observable<List<Student>> query(String name);
然後我們的需求是一個一個的輸出學生姓名,實作如下:
query("王").subscribe(list -> {
for(Student student:list){
Log.i(TAG,student.getName());
});
- flatMap操作符
query("王").flatMap(list -> Observable.from(list))
.subscribe(student ->Log.i(TAG,student.getName());
);
上面的例子用flatMap操作符,就可以變得很簡潔,flatMap操作符的功能是接收一個接收一個Observable的輸出作為輸入,同時輸出另外一個Observable,通常是接收一個list,然後逐一發送list的元素。比如這邊的Student數組,變成了逐一發送student的Observable。
- Map操作符
query("王").flatMap(list -> Observable.from(list))
.Map(student->return student.getGrade())
.subscribe(grade->Log.i(TAG,grade+"");
);
現在我們隻想輸出每個學生的成績,我們就需要Map操作符,它的功能是接收一種類型的Observable,轉化為另外一種Observable,比如這邊的Student類型轉化為了Int型的Observable。
query("王").flatMap(list -> Observable.from(list))
.Map(student->return student.getGrade())
.subscribe(grade->Log.i(TAG,grade+"");
);
- filter操作符
query("王").flatMap(list -> Observable.from(list))
.Map(student->return student.getGrade())
.filter(grade->grade>80)
.subscribe(grade->Log.i(TAG,grade+"");
);
顧名思義filter操作符就是過濾用的,相當于加個判斷條件,比如這邊的就是加上分數大于80的條件.
- take操作符
query("王").flatMap(list -> Observable.from(list))
.Map(student->return student.getGrade())
.filter(grade->grade>80)
.take(5)
.subscribe(grade->Log.i(TAG,grade+"");
);
take操作符的功能是限定個數,比如這邊的功能就是限定我最多需要5個成績。
- doOnNext操作符
query("王").flatMap(list -> Observable.from(list))
.Map(student->return student.getGrade())
.filter(grade->grade>80)
.take(5)
.doOnNext(grade->save(grade))
.subscribe(grade->Log.i(TAG,grade+"");
);
doOnNext()允許我們在每次輸出一個元素之前做一些額外的事情,比如這裡的我們用來儲存成績。
- subscribeOn/observeOn操作符
query("王").flatMap(list -> Observable.from(list))
.Map(student->return student.getGrade())
.filter(grade->grade>80)
.take(5)
.doOnNext(grade->save(grade))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(grade->Log.i(TAG,grade+"");
);
這兩個操作符一般都是成對出現的,他們的功能就是切換線程。subscribeOn是指定被觀察者的線程,observeOn是指定觀察者的線程。比如這個例子中前面的訂閱的工作在IO線程做,後面的列印功能在主線程做。
-
小結
怎麼樣,看起來我好像做了很多事情,又有判斷資料,又有儲存資料,又有選取資料,關鍵還有線程切換,然而,我實際上就寫了那麼一點代碼,看起來是不是酷!這就是RxJava的魅力所在。
RxAndroid
一開始說了,RxAndroid其實跟RxJava是差不多的,但是總歸還是有一點變化的。比如Android上會有生命周期的問題,可能會導緻記憶體洩漏:Observable持有Context導緻的記憶體洩露。在這個問題上,我們的解決方法是這樣的:
private Subscription mTestSubscription= Subscriptions.empty();
public void test(){
mTestSubscription=myObservable.subscribe(TestObserver);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mTestSubscription != null && !mTestSubscription.isUnsubscribed()) {
mTestSubscription.unsubscribe();
}
}
就是在訂閱的時候,用一個Subscription來儲存它,然後在退出這個Activity的時候取消訂閱。
另外還有一些專門為Android設計的RxView,比如以下防抖動的View:
RxView.clicks(btn_click)
.throttleFirst(3, TimeUnit.SECONDS)
.subscribe();
總結
終于是把這八篇文章寫完了!MVP+Retrofit+dagger2+RxAndroid這套架構真的是很不錯的一套架構,希望越來越多的人使用它吧!