編輯:關於Android編程
最近諸事纏身,有點忙,終於抽出時間&&有興致寫第三了,有一股深深的罪惡感,廢話不多說,還是直接接上篇的活了,講一講一些比較常用的操作符吧。國際慣例,先丟兩個傳送門。
然後這篇講RxJava中強大的Scheduler調度器 ,就是因為它,RxJava才能極其簡便的在線程中切換,接著再講一講一些常用的操作符,比較簡單容易理解的操作符都在本篇羅列出來,以後可能不定時更新這篇文章,復雜的操作符後續分篇講。
在講常用操作符前,先看看Scheduler這個東西,名之為調度器,正因為有這個東西,讓RxJava可以從主線程和子線程之間輕松切換,各個Scheduler的具體使用效果看以下表解釋:
具體如何使用呢,比如從數據庫讀取數據更新到UI上,假設數據量很大,直接從主線程讀取數據,會造成UI卡頓,以前我們常用AnsyTask或者Handler去處理避免出現這類問題,個人認為手寫個AnsyTask還是挺麻煩的,但用RxJava就簡單多了,例如:
Observable.create(new Observable.OnSubscribe() { @Override public void call(Subscriber subscriber) { Data data = getData();//從數據庫獲取 subscriber.onNext(data); subscriber.onCompleted(); }}) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1() { @Override public void call(Data data) { //更新ui } });
簡單粗暴的解釋一下,subscribeOn( )決定了發射數據在哪個調度器上執行,observeOn(AndroidSchedulers.mainThread())則指定數據接收發生在UI線程,簡直不要太方便。
Map:最常用且最實用的操作符之一,將對象轉換成另一個對象發射出去,應用范圍非常廣,如數據的轉換,數據的預處理等。
例一:數據類型轉換,改變最終的接收的數據類型。假設傳入本地圖片路徑,根據路徑獲取圖片的Bitmap。
Observable.just(filePath).map(new Func1() { @Override public Bitmap call(String path) { return getBitmapByPath(path); }}).subscribe(new Action1 () { @Override public void call(Bitmap bitmap) { //獲取到bitmap,顯示 }});
例二:對數據進行預處理,最後得到理想型數據。實際開發過程中,從後台接口獲取到的數據也許不符合我們想要的,這時候可以在獲取過程中對得到的數據進行預處理(結合Retrofit)。
Observable.just("12345678").map(new Func1() { @Override public String call(String s) { return s.substring(0,4);//只要前四位 }}) .subscribe(new Action1 () { @Override public void call(String s) { Log.i("mytag",s); }});
先說明一下,為了方便理解,所以寫的例子都比較簡單,不要以為明明可以簡單用if-else解決的事,沒必要用這種方式去寫,當你真正將這些操作符使用到數據處理中去的時候,你就會發現有多方便。
FlatMap:和Map很像但又有所區別,Map只是轉換發射的數據類型,而FlatMap可以將原始Observable轉換成另一個Observable。還是舉例說明吧。假設要打印全國所有學校的名稱,可以直接用Map:
為了更清晰一點,先貼一下School類:
public class School { private String name; private ListstudentList; public List getStudentList() { return studentList; } public void setStudentList(List studentList) { this.studentList = studentList; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static class Student{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
接著用Map打印學校名稱:
ListschoolList = new ArrayList<>(); Observable.from(schoolList).map(new Func1 () { @Override public String call(School school) { return school.getName(); }}).subscribe(new Action1 () { @Override public void call(String schoolName) { Log.i("mytag",schoolName); }});
再進一步,打印學校所有學生的姓名,先考慮用Map實現,將所有School對象直接轉成Student:
Observable.from(schoolList).map(new Func1() { @Override public School.Student call(School school) { return school.getStudentList(); }}).subscribe(new Action1 () { @Override public void call(School.Student student) { Log.i("mytag",student.getName()); }});
看似可行,但事實上,這是一段錯誤的代碼,細心的人就會發現錯誤的地方
@Override public School.Student call(School school) { return school.getStudentList(); //錯誤,Student 是一個對象,返回的卻是一個list }
所以用Map是無法實現直接打印學校的所有學生名字的,因為Map是一對一的關系,無法將單一的School對象轉變成多個Student。前面說到,FlatMap可以改變原始Observable變成另外一個Observable,如果我們能利用from()操作符把school.getStudentList()變成另外一個Observable問題不就迎刃而解了嗎,這時候就該FlatMap上場了,來看看它是怎麼實現的:
Observable.from(schoolList).flatMap(new Func1>() { @Override public Observable call(School school) { return Observable.from(school.getStudentList()); //關鍵,將學生列表以另外一個Observable發射出去 }}).subscribe(new Action1 () { @Override public void call(School.Student student) { Log.i("mytag",student.getName()); }});
Map和FlatMap在我看來就像孿生兄弟一樣,非常實用,實際開發中也我也經常使用,個人覺得要想上手RxJava,掌握這兩個操作符必不可少。
Buffer:緩存,可以設置緩存大小,緩存滿後,以list的方式將數據發送出去;例:
Observable.just(1,2,3).buffer(2).subscribe(new Action1>() { @Override public void call(List
list) { Log.i("mytag","size:"+list.size()); }});
運行打印結果如下:
11-02 20:49:58.370 23392-23392/? I/mytag: size:2 11-02 20:49:58.370 23392-23392/? I/mytag: size:1
在開發當中,個人經常將Buffer和Map一起使用,常發生在從後台取完數據,對一個List中的數據進行預處理後,再用Buffer緩存後一起發送,保證最後數據接收還是一個List,如下:
ListschoolList = new ArrayList<>(); Observable.from(schoolList).map(new Func1 () { @Override public School call(School school) { school.setName("NB大學"); //將所有學校改名 return school; }}).buffer(schoolList.size()) //緩存起來,最後一起發送 .subscribe(new Action1 >() { @Override public void call(List
schools) { }});
Observable.from(schoolList).take(4).map(new Func1() { @Override public School call(School school) { school.setName("NB大學"); return school; }}).buffer(4).subscribe(new Action1 >() { @Override public void call(List
schools) { }});
Observable.just(1, 2, 1, 1, 2, 3) .distinct() .subscribe(new Action1輸出() { @Override public void call(Integer item) { System.out.println("Next: " + item); } });
Next: 1 Next: 2 Next: 3
Observable.just(1, 2, 3, 4, 5) .filter(new Func1輸出:() { @Override public Boolean call(Integer item) { return( item < 4 ); } }).subscribe(new Action1 () { @Override public void call(Integer item) { System.out.println("Next: " + item); }});
Next: 1 Next: 2 Next: 3
這一篇就先講這麼多吧,重點掌握Map和FlatMap操作符,因為真的很實用、很實用、很實用,重要的事講三遍。
費了好久終於下載好了源碼4.4.2 (如果想只是了解下編譯過程 能用現成的最好了)下載好後 接下來開始編譯了我的虛擬機Ubuntu配置 源碼有16g+ (.repo 占了
Android開發本質上就是手機和web服務器之間進行通信,從服務端需要獲取數據,但是當訪問的數據比較大,比較多,並且是重復數據時,會極大影響性能,甚至應用崩潰,手機卡死
Android 自定義View需要重寫ondraw()等方法,這篇博客給大家說說自定義View的寫法,需要我們繼承View,然後重寫一些 方法,方法多多,看你需要什麼方
演示效果主要代碼如下自定義的一個EditText,用於實現有文字的時候顯示可以清楚的按鈕:import android.content.Context;import an