Android RxVolley = Volley + RxJava + OkHttp
阿新 • • 發佈:2017-10-11
ext vol pst 之前 timeout subscribe == thread 復用
- Github:https://github.com/kymjs/RxVolley
- RxVolley使用文檔 V1.0:http://rxvolley.mydoc.io/
一.RxVolley使用指南
1.概述
RxVolley是一個基於Volley的網絡請求庫;同時支持RxJava;可以選擇使用OKHttp替代默認的 HttpUrlConnection 做網絡請求;可以選擇使用圖片加載功能(復用的網絡請求將有效減少apk體積);移除了原Volley的 HttpClient 相關 API ,可在 API23 環境編譯;內置了RxBus的實現,可有效替換掉EventBus等相關庫;
2.依賴
使用RxVolley,需要在你的build.gradle文件中加入
compile ‘com.kymjs.rxvolley:rxvolley:1.0.7‘
如果你還想使用OKhttp來替代默認的HttpUrlconnection,需要加入
compile ‘com.kymjs.rxvolley:okhttp:1.0.7‘
如果你想使用RxVolley的圖片加載功能(復用http模塊可以有效減少apk大小),需要加入
compile ‘com.kymjs.rxvolley:bitmapcore:1.0.7‘
使用 RxVolley 做網絡請求
3.簡單實現
//get請求簡潔版實現 RxVolley.get("http://www.kymjs.com/feed.xml", new HttpCallback() { @Override public void onSuccess(String t) { Loger.debug("請求到的數據:" + t); } }); //post請求簡潔版實現 HttpParams params = new HttpParams(); params.put("name", "kymjs"); params.put("age", 18);params.put("image", new File("path"))//文件上傳 RxVolley.post("http://kymjs.com/feed.xml", params, new HttpCallback() { @Override public void onSuccess(String t) { Loger.debug("請求到的數據:" + t); } });
4.對Cookie等請求頭的處理
//用戶登錄邏輯(HttpCallback中有很多重載方法,可以選擇需要的實現) HttpParams params = new HttpParams(); params.put("name", "kymjs"); params.put("age", 18); params.put("password", "helloword"); RxVolley.post("http://kymjs.com/login", params, new HttpCallback() { @Override public void onSuccess(Map<String, String> headers, byte[] t) { Loger.debug("請求到的數據:" + new String(t)); // 獲取到的cookie Loger.debug("===" + headers.get("Set-Cookie")); } });
//向服務器傳遞cookie信息 HttpParams params = new HttpParams(); params.put("name", "kymjs"); params.put("age", 100); params.putHeaders("cookie", "your cookie"); RxVolley.post("http://kymjs.com/update", params, new HttpCallback() { @Override public void onSuccess(String t) { Loger.debug("請求到的數據:" + t); } });
比起 入門 章節講述的網絡請求,你可能希望有更多的需求
5.構建網絡請求
HttpParams params = new HttpParams(); //同之前的設計,傳遞 http 請求頭可以使用 putHeaders() params.putHeaders("cookie", "your cookie"); params.putHeaders("User-Agent", "rxvolley"); //傳遞 http 請求參數可以使用 put() params.put("name", "kymjs"); params.put("age", "18"); //http請求的回調,內置了很多方法,詳細請查看源碼 //包括在異步響應的onSuccessInAsync():註不能做UI操作 //網絡請求成功時的回調onSuccess() //網絡請求失敗時的回調onFailure():例如無網絡,服務器異常等 HttpCallback callback = new HttpCallback(){ @Override public void onSuccessInAsync(byte[] t) { } @Override public void onSuccess(String t) { } @Override public void onFailure(int errorNo, String strMsg) { } } ProgressListener listener = new ProgressListener(){ /** * @param transferredBytes 進度 * @param totalSize 總量 */ @Override public void onProgress(long transferredBytes, long totalSize){ } } new RxVolley.Builder() .url("http://www.kymjs.com/rss.xml") //接口地址 //請求類型,如果不加,默認為 GET 可選項: //POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH .httpMethod(RxVolley.Method.GET) //設置緩存時間: 默認是 get 請求 5 分鐘, post 請求不緩存 .cacheTime(6) //內容參數傳遞形式,如果不加,默認為 FORM 表單提交,可選項 JSON 內容 .contentType(RxVolley.ContentType.FORM) .params(params) //上文創建的HttpParams請求參數集 //是否緩存,默認是 get 請求 5 緩存分鐘, post 請求不緩存 .shouldCache(true) .progressListener(listener) //上傳進度 .callback(callback) //響應回調 .encoding("UTF-8") //編碼格式,默認為utf-8 .doTask(); //執行請求操作
6.對 RxJava 的支持
RxVolley 支持返回一個 Observable 類型的數據,如下是 Result 類的原型
public class Result { public Map<String, String> header; public byte[] data; public Result(Map<String, String> header, byte[] data) { this.header = header; this.data = data; } }
執行一次請求,並返回 Observable
Observable<Result> observable = new RxVolley.Builder() .url("http://www.kymjs.com/rss.xml") //default GET or POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH .httpMethod(RxVolley.Method.POST) .cacheTime(6) //default: get 5min, post 0min .params(params) .contentType(RxVolley.ContentType.JSON) .getResult(); // 使用getResult()來返回RxJava數據類型 //當拿到 observable 對象後,你可以設置你自己的 subscriber observable.subscribe(subscriber);
完整的使用示例
public class MainActivity extends AppCompatActivity { private Subscription subscription; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Observable<Result> observable = new RxVolley.Builder() .url("http://kymjs.com/feed.xml") .contentType(RxVolley.ContentType.FORM) .getResult(); subscription = observable .map(new Func1<Result, String>() { @Override public String call(Result result) { return new String(result.data); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<String>() { @Override public void call(String result) { Log.i("kymjs", "======網絡請求" + result); } }); } @Override protected void onDestroy() { super.onDestroy(); if (subscription != null && subscription.isUnsubscribed()) { subscription.unsubscribe(); } } }
7.自定義請求
也許你是 Volley 的重度使用者(就像我),那麽你一定是因為 Volley 自由的擴展性而愛上它的。
你可以通過創建一個Request
RxVolley.Builder().setRequest(yourRequest).doTask();
去執行你的自定義 Request
一個典型自定義Request的示例:
/** * Form表單形式的Http請求 */ public class FormRequest extends Request<byte[]> { private final HttpParams mParams; public FormRequest(RequestConfig config, HttpParams params, HttpCallback callback) { super(config, callback); if (params == null) { params = new HttpParams(); } this.mParams = params; } @Override public String getCacheKey() { if (getMethod() == RxVolley.Method.POST) { return getUrl() + mParams.getUrlParams(); } else { return getUrl(); } } @Override public String getBodyContentType() { if (mParams.getContentType() != null) { return mParams.getContentType(); } else { return super.getBodyContentType(); } } @Override public ArrayList<HttpParamsEntry> getHeaders() { return mParams.getHeaders(); } @Override public byte[] getBody() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { mParams.writeTo(bos); } catch (IOException e) { Loger.debug("FormRequest#getBody()--->IOException writing to ByteArrayOutputStream"); } return bos.toByteArray(); } @Override public Response<byte[]> parseNetworkResponse(NetworkResponse response) { return Response.success(response.data, response.headers, HttpHeaderParser.parseCacheHeaders(getUseServerControl(), getCacheTime(), response)); } @Override protected void deliverResponse(ArrayList<HttpParamsEntry> headers, final byte[] response) { if (mCallback != null) { HashMap<String, String> map = new HashMap<>(headers.size()); for (HttpParamsEntry entry : headers) { map.put(entry.k, entry.v); } mCallback.onSuccess(map, response); } } @Override public Priority getPriority() { return Priority.IMMEDIATE; } }
8.文件(圖片)下載
利用 RxVolley 的自定義請求,在庫中內置了文件下載功能。你可以使用
//下載進度(可選參數,不需要可不傳) listener = new ProgressListener() { @Override public void onProgress(long transferredBytes, long totalSize) { Loger.debug(transferredBytes + "======" + totalSize); } } //下載回調,內置了很多方法,詳細請查看源碼 //包括在異步響應的onSuccessInAsync():註不能做UI操作 //下載成功時的回調onSuccess() //下載失敗時的回調onFailure():例如無網絡,服務器異常等 HttpCallback callback = new HttpCallback(){ @Override public void onSuccessInAsync(byte[] t) { } @Override public void onSuccess(String t) { } @Override public void onFailure(int errorNo, String strMsg) { } } RxVolley.download(FileUtils.getSDCardPath() + "/a.apk", "https://www.oschina.net/uploads/osc-android-app-2.4.apk", listener, callback);
download()原型
既然說了下載功能是利用 RxVolley 的自定義請求創建的,不妨看看他的方法實現:
/** * 下載 * * @param storeFilePath 本地存儲絕對路徑 * @param url 要下載的文件的url * @param progressListener 下載進度回調 * @param callback 回調 */ public static void download(String storeFilePath, String url, ProgressListener progressListener, HttpCallback callback) { RequestConfig config = new RequestConfig(); config.mUrl = url; FileRequest request = new FileRequest(storeFilePath, config, callback); request.setOnProgressListener(progressListener); new Builder().setRequest(request).doTask(); }
9.更多可選設置
理論上來說,一切的請求設置都可以通過自定義 Request 來完成。
但是,如果你和我一樣是個懶人,當然更希望這些早就有人已經做好了。
- 設置文件緩存的路徑
默認的文件緩存路徑是在SD卡根目錄的 /RxVolley 文件夾下,你可以通過如下語句設置你的 cacheFolder
RxVolley.setRequestQueue(RequestQueue.newRequestQueue(cacheFolder));
需要註意的是,setRequestQueue 方法必須在 RxVolley.Build() 方法執行之前調用,也就是在使用 RxVolley 以前先設置配置信息。建議在 Application 類中完成這些設置。
- Https設置
如果不設置,默認信任全部的https證書。可以傳入自定義 SSLSocketFactory
RxVolley.setRequestQueue(RequestQueue.newRequestQueue(cacheFolder), new HttpConnectStack(null, sslSocketFactory));
需要註意的是,setRequestQueue 方法必須在 RxVolley.Build() 方法執行之前調用,也就是在使用 RxVolley 以前先設置配置信息。建議在 Application 類中完成這些設置。
一個自定義設置SSLSocketFactory的相關示例:
//下載的證書放到項目中的assets目錄中 InputStream ins = context.getAssets().open("app_pay.cer"); CertificateFactory cerFactory = CertificateFactory .getInstance("X.509"); Certificate cer = cerFactory.generateCertificate(ins); KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC"); keyStore.load(null, null); keyStore.setCertificateEntry("trust", cer); SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore); RxVolley.setRequestQueue(RequestQueue.newRequestQueue(RxVolley.CACHE_FOLDER), new HttpConnectStack(null, sslSocketFactory));
Build()中的可選設置
詳細請參閱 RxVolley$Builder 類中代碼。
//請求超時時間 timeout() //為了更真實的模擬網絡,如果讀取緩存,延遲一段時間再返回緩存內容 delayTime() //緩存有效時間,單位分鐘 cacheTime() //使用服務器控制的緩存有效期,即cookie有效期 //(如果使用服務器端控制,則無視#cacheTime()) useServerControl() //啟用緩存 shouldCache() //重連策略,Volley默認的重連策略是timeout=3000,重試1次 retryPolicy()
二.Cookie持久化封裝
RxVolley 默認對於 cookie 的操作是會從 HttpCallback 中返回 cookie,需要手動保存到本地。
如果你希望框架能夠自動存儲 cookie,可以這麽做:
按需要選擇繼承FormRequest或者JsonRequest (直接繼承 Request 類也可以,但是復雜) 並重寫
@Override protected void deliverResponse(ArrayList<HttpParamsEntry> headers, final byte[] response) { if (mCallback != null) { HashMap<String, String> map = new HashMap<>(headers.size()); for (HttpParamsEntry entry : headers) { map.put(entry.k, entry.v); } mCallback.onSuccess(map, response); } }
邏輯如上述代碼,其中的map即包含了服務器返回的cookie,可以做你自己的操作了。
最終執行你的自定義 Request
new RxVolley.Builder().setRequest(xxxxx).doTask();
在傳遞 Cookie 作為請求頭的時候,建議寫一個工具類,例如
public static HttpParams getHttpParams() { HttpParams params = new HttpParams(); params.putHeader("cookie"); return params; }
三.使用 OkHttp
使用 OkHttp 替代HttpUrlconnection
Volley 允許你創建自己的網絡請求執行器,執行器需要實現IHttpStack接口
RxVolley 的 okhttp module 已經有了使用 OkHttp 作為請求執行器的實現。
你可以使用如下代碼設置,依舊需要註意的是,setRequestQueue 方法必須在 RxVolley.Build() 方法執行之前調用,也就是在使用 RxVolley 以前先設置配置信息。建議在 Application 類中完成這些設置。
RxVolley.setRequestQueue(RequestQueue.newRequestQueue(RxVolley.CACHE_FOLDER, new OkHttpStack(new OkHttpClient())));
使用 OkHttp 相關功能需要在你的 build.gradle 文件中加入
compile ‘com.kymjs.rxvolley:okhttp:1.0.5‘
四.Issue反饋
- https://github.com/kymjs/RxVolley/issues
Android RxVolley = Volley + RxJava + OkHttp