OkHttpPlus介紹
項目地址:https://github.com/ZhaoKaiQiang/OkHttpPlus
主要功能:OkHttp封裝,支持GET、POST、UI線程回調、JSON格式解析、鏈式調用、小文件上傳下載及進度監聽等功能
爲什麼要寫這麼一個庫呢?
首先,是因爲OkHttp在4.4之後已經作爲底層的Http實現了,所以OkHttp這個庫很強大,值得我們學習。
其次,在我看來,OkHttp使用起來不如Volley方便,OkHttp的回調都是在工作線程,所以如果在回調裏面操作View的話,需要自己轉換到UI線程,非常繁瑣,所以需要封裝。也有將OkHttp作爲Volley底層Http實現的用法,發送請求、維護請求隊列用的是Volley,實際的Http請求用的是OkHttp。
關於Volley和oOkHttp結合的Demo請戳煎蛋項目
如何使用
初始化
你可以在Application裏面完成初始化,因爲對OkHttp的封裝主要使用的是代理設計模式,使用OkHttpProxy.getInstance()
可以獲取到單例客戶端,你可以像沒封裝之前一樣,設置任意的參數,比如下面就設置超時時間和忽略HTTPS認證。
public class OkApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
OkHttpClient okHttpClient = OkHttpProxy.getInstance();
okHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(15, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(15, TimeUnit.SECONDS);
//ignore HTTPS Authentication
okHttpClient.setHostnameVerifier(new MyHostnameVerifier());
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());
okHttpClient.setSslSocketFactory(sc.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
}
Get方法
你大多數情況下是和OkHttpProxy這個代理類打交道,而且OkHttpPlus支持鏈式調用,內部採用Builder設計模式,所以你可以像下面這樣使用
OkHttpProxy.get()
.url(URL_USER)
.tag(this)
.execute(new OkCallback<User>(new OkJsonParser<User>() {
}) {
@Override
public void onSuccess(int code, User user) {
tv_response.setText(user.toString());
}
@Override
public void onFailure(Throwable e) {
tv_response.setText(e.getMessage());
}
});
爲了支持返回值解析,這裏我採用了泛型,在OkCallback的構造函數中,你需要傳入一個解析器,OkHttpPlus內部支持5種解析器,這可以解決你大部分的需求
- OkBaseParser,所有解析器的基類,不可直接使用
- OkBaseJsonParser,所有JSON解析器的基類,你可以繼承它來定義自己的JSON解析
- OkJsonParser,JSON解析器,支持JSONObject和JSONArray的解析,默認使用GSON作爲解析器
- OkTextParser,String解析器,支持將結果以String方式輸出
- OkFileParser,文件解析器,支持將結果保存爲文件,你可以用來下載文件,但是不支持較大文件下載
所以如果你想獲取一個JSONArray,你可以像下面這樣
OkHttpProxy.get()
.url(URL_USER)
.tag(this)
.execute(new OkCallback<List<User>>(new OkJsonParser<List<User>>() {
}) {
@Override
public void onSuccess(int code, List<User> users) {
tv_response.setText(users.toString());
}
@Override
public void onFailure(Throwable e) {
tv_response.setText(e.getMessage());
}
});
你如果想獲取String數據,你可以這樣
OkHttpProxy.get()
.url(URL_BAIDU)
.tag(this)
.execute(new OkCallback<String>(new OkTextParser()) {
@Override
public void onSuccess(int code, String s) {
tv_response.setText(s);
}
@Override
public void onFailure(Throwable e) {
tv_response.setText(e.getMessage());
}
});
當然,如果你想自定義一個解析器,也是完全可以的。
OkHttpPlus的解析器部分使用的是策略設計模式,所以你可以像下面這樣自定義一個解析策略,完成結果的解析
public class JokeParser<T> extends OkJsonParser<T> {
@Nullable
@Override
public T parse(Response response) throws IOException {
String jsonStr = response.body().string();
try {
jsonStr = new JSONObject(jsonStr).getJSONArray("comments").toString();
return mGson.fromJson(jsonStr, new TypeToken<ArrayList<Joke>>() {
}.getType());
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
然後就可以將返回結果解析爲ArrayList了
OkHttpProxy.get()
.url(Joke.getRequestUrl(1))
.tag(this).execute(new OkCallback<List<Joke>>(new JokeParser()) {
@Override
public void onSuccess(int code, List<Joke> jokes) {
tv_response.setText(jokes.toString());
}
@Override
public void onFailure(Throwable e) {
tv_response.setText(e.getMessage());
}
});
Post方法
Post的方法與Get方法使用類似,你可以像下面這樣發送POST請求,並添加Header和Params。
OkHttpProxy
.post()
.url(URL_USERS)
.tag(this)
.addParams("name", "zhaokaiqiang")
.addHeader("header", "okhttp")
.execute(new OkCallback<ArrayList<User>>(new OkJsonParser<ArrayList<User>>() {
}) {
@Override
public void onSuccess(int code, ArrayList<User> users) {
tv_response.setText(users.toString());
}
@Override
public void onFailure(Throwable e) {
tv_response.setText(e.getMessage());
}
});
你可能注意到了,在發送每個請求的時候,我都調用了tag()方法,所以你可以在不需要的時候,將請求取消掉。
@Override
protected void onDestroy() {
super.onDestroy();
OkHttpProxy.cancel(this);
}
下載
你可以像下面這樣下載一個文件,但是由於下載的內容都在內存中,所以不支持大文件下載,否則會OOM
String desFileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
OkHttpProxy.download(URL_DOWMLOAD, new DownloadListener(desFileDir, "json.jar") {
@Override
public void onUIProgress(Progress progress) {
//當下載資源長度不可知時,progress.getTotalBytes()爲-1,此時不能顯示下載進度
int pro = (int) (progress.getCurrentBytes() / progress.getTotalBytes() * 100);
if (pro > 0) {
pb.setProgress(pro);
}
KLog.d("pro = " + pro + " getCurrentBytes = " + progress.getCurrentBytes() + " getTotalBytes = " + progress.getTotalBytes());
}
@Override
public void onSuccess(File file) {
tv_response.setText(file.getAbsolutePath());
}
@Override
public void onFailure(Exception e) {
tv_response.setText(e.getMessage());
}
});
}
上傳
OkHttpPlus也支持小文件上傳,我這裏測試使用的是七牛的上傳API,Token是有期限的,所以你需要在下面網址自己生成測試
/**
* 採用七牛上傳接口,Token有效期爲12小時,若Token無效,請在下面自行獲取
* Token生成網址 http://jsfiddle.net/gh/get/extjs/4.2/icattlecoder/jsfiddle/tree/master/uptoken
* <p/>
* AK = IUy4JnOZHP6o-rx9QsGLf9jMTAKfRkL07gNssIDA
* CK = DkfA7gPTNy1k4HWnQynra3qAZhrzp-wmSs15vub6
* BUCKE_NAME = zhaokaiqiang
*/
public void uploadFile(View view) {
File file = new File(Environment.getExternalStorageDirectory(), "jiandan02.jpg");
if (!file.exists()) {
Toast.makeText(MainActivity.this, "文件不存在,請修改文件路徑", Toast.LENGTH_SHORT).show();
return;
}
Map<String, String> param = new HashMap<>();
param.put("token", TOKEN);
Pair<String, File> pair = new Pair("file", file);
OkHttpProxy
.upload()
.url(URL_UPLOAD)
.file(pair)
.setParams(param)
.setWriteTimeOut(20)
.start(new UploadListener() {
@Override
public void onSuccess(Response response) {
tv_response.setText("isSuccessful = " + response.isSuccessful() + "\n" + "code = " + response.code());
}
@Override
public void onFailure(Exception e) {
tv_response.setText(e.getMessage());
}
@Override
public void onUIProgress(Progress progress) {
int pro = (int) ((progress.getCurrentBytes() + 0.0) / progress.getTotalBytes() * 100);
if (pro > 0) {
pb.setProgress(pro);
}
KLog.d("pro = " + pro + " getCurrentBytes = " + progress.getCurrentBytes() + " getTotalBytes = " + progress.getTotalBytes());
}
});
}
靈感來源
本項目的靈感和部分代碼來自於下面兩個開源項目,謝謝他們的分享精神
尊重原創,轉載請註明:From 凱子哥(http://blog.csdn.net/zhaokaiqiang1992) 侵權必究!
關注我的微博,可以獲得更多精彩內容