標籤:completed cep switch font password override async [] break
RX系列四 | RxAndroid | 載入圖片 | 提交表單
說實話,學RxJava就是為了我們在Android中運用的更加順手一點,也就是RxAndroid,我們還是先一步步來,學會怎麼去用的比較好,之前的三篇算是鋪墊,讓你有一點認識,那Rx在Android中有什麼好處呢?我們先類比一些原始功能和他對比下
一.載入圖片
很多人說Rx出來之後,是編程思想的一種進階,實際上我學習了這種思想之後,確實是覺得有了很大的改變,不過,需要一點學習成本再加上,需要對原先的思想有些改觀,使得我依舊有點不適應,不知道為啥,可能就像用了好幾年的Eclipse,突然讓我用Android Studio的時候的那種感覺,不過,技術在進步,每個人也需要去接受,沒有好壞之分,那我們就在講解Rx之前,我們先把思路,邏輯來做一個鋪墊吧,首先,我們要準備一些東西的,因為涉及了網路請求,下載等功能,所以我們肯定是要去添加下網路許可權
<!--網路許可權--> <uses-permission android:name="android.permission.INTERNET"/>
然後我們再來說一下,我們現在要乾的事情,先易後難,我們先來載入一張圖片,我們傳統的做法是通過AsyncTask去做,但是這樣的代碼很長很沉悶,而在我們的Activity中,其實上一個Activity的本身他是有很多的工作要做的,這樣導致代碼會很多,不容易重構等,所以才會有現在的MVC,MVP等架構去解耦,所以我們既然Rx編程本身是一套很簡潔的代碼,那我們應該用什麼方法去合理的實現呢?我們來寫個解析的方法,因為需要用到OkHttp,所以請在gradle裡添加
//OkHttp3 compile ‘com.squareup.okhttp3:okhttp:3.+‘
這樣才好去載入,我們寫個方法吧
//載入圖片 private Observable<byte[]> lodingImg(String imgPath){ return Observable.create(new Observable.OnSubscribe<byte[]>() { @Override public void call(Subscriber<? super byte[]> subscriber) { if(!subscriber.isUnsubscribed()){ //解析圖片 OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(imgPath).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { subscriber.onError(e); } @Override public void onResponse(Call call, Response response) throws IOException { if(response.isSuccessful()){ byte [] bytes = response.body().bytes(); if(bytes != null){ subscriber.onNext(bytes); } } //結束 subscriber.onCompleted(); } }); } } }); }
這個方法可以看到我們傳回值是一個byte位元組數組參數的被觀察者Observable,然後傳遞一個地址,我們就直接return回去一個Observable,在Observable裡面,我們做了什麼事情呢?其實我們就直接用OkHttp去解析了一張圖片,拿到了byte之後,通過subscriber.onNext(bytes)傳遞給了觀察者,讓他去做操作,當然,別忘了調用onCompleted去告知觀察者已經結束了操作,而在觀察者這邊,你需要做什麼呢?
@Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_download: lodingImg(IMG_PATH) //網路訪問 .observeOn(Schedulers.io()) //UI線程 .observeOn(AndroidSchedulers.mainThread()) //訂閱 .subscribe(new Observer<byte[]>() { @Override public void onCompleted() { Log.i(TAG,"onCompleted"); } @Override public void onError(Throwable e) { Log.i(TAG,e.toString()); } @Override public void onNext(byte[] bytes) { Bitmap bitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length); img.setImageBitmap(bitmap); } }); break; } }
其實可以看到,我們直接就去訂閱了一個subscribe,在onNext裡面,通過BitmapFactory的方法轉換成一個Bitmap,這就是Rx載入的處理方式,這種方式將對我們產生很大的影響,我們最起碼現在懂得了他的一點套路了,我們來看下運行結果
OK,也是很順利的載入出來了
二.提交表單
如果說載入圖片是get的話,那提交表單就是post了,我們來看一下提交表單該怎麼寫,我們假設是做一個登陸註冊的功能,那就很簡單了,我們看下我們這次要做的代碼
//登入 private Observable<String> fromLogin(String url, Map<String,String> params){ return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { if(!subscriber.isUnsubscribed()){ OkHttpClient client = new OkHttpClient(); FormBody.Builder builder = new FormBody.Builder(); if(params!=null && !params.isEmpty()){ for (Map.Entry<String, String>entry:params.entrySet()){ builder.add(entry.getKey(),entry.getValue()); } } RequestBody requestBody = builder.build(); //構建post請求 Request request = new Request.Builder().url(url).post(requestBody).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { subscriber.onError(e); } @Override public void onResponse(Call call, Response response) throws IOException { if(response.isSuccessful()){ subscriber.onNext(response.body().string()); } //訪問結束 subscriber.onCompleted(); } }); } } }); }
這段代碼裡面,我們可用看到,我們定義了一個方法,傳回值是一個String類型的被觀察者Observable,而傳遞的參數就是登陸的地址和一個Map索引值對,我們直接return一個Observable即可,在裡面我們使用OkHTTP提交表單,最後通過onNext返回結果,通過onCompleted告知結束操作,而在我們的觀察者裡面我們應該怎麼做?
@Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_login: String name = et_name.getText().toString().trim(); String password = et_password.getText().toString().trim(); if (!TextUtils.isEmpty(name)) { if(!TextUtils.isEmpty(password)){ Map<String,String> params = new HashMap<>(); params.put("name",name); params.put("password",password); fromLogin(LOGIN_URL,params) //網路訪問 .observeOn(Schedulers.io()) //UI線程 .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<String>() { @Override public void onCompleted() { Log.i(TAG,"onCompleted"); } @Override public void onError(Throwable e) { Log.i(TAG,e.toString()); } @Override public void onNext(String s) { Log.i(TAG,s); } }); }else { Toast.makeText(this, "密碼不可為空", Toast.LENGTH_SHORT).show(); } }else { Toast.makeText(this, "帳號不可為空", Toast.LENGTH_SHORT).show(); } break; } }
在這個點擊事件裡,我們可用看到直接把參數塞進去後通過subscribe訂閱拿到結果,這樣如果登入成功就跳轉了,這就是一整套的邏輯,這裡沒有地址,就不示範了,到這裡,我相信大家對基本的使用應該是沒什麼問題了,一句話概括,就是非同步,讓我們的代碼邏輯性更強,當然, 現在的例子還不能友好的表達出精髓,大家有興趣的可以接著後續的系列
Sample下載:系列最後一篇提供有興趣的可以加群:555974449
RX系列四 | RxAndroid | 載入圖片 | 提交表單