OkHttpPlus介紹
項目地址:https://github.com/ZhaoKaiQiang/OkHttpPlus
主要功能:OkHttp封裝辫红,支持GET、POST祝辣、UI線程回調(diào)厉熟、JSON格式解析、鏈?zhǔn)秸{(diào)用较幌、小文件上傳下載及進(jìn)度監(jiān)聽等功能
為什么要寫這么一個庫呢揍瑟?
首先,是因為OkHttp在4.4之后已經(jīng)作為底層的Http實現(xiàn)了乍炉,所以O(shè)kHttp這個庫很強大绢片,值得我們學(xué)習(xí)。
其次岛琼,在我看來底循,OkHttp使用起來不如Volley方便,OkHttp的回調(diào)都是在工作線程槐瑞,所以如果在回調(diào)里面操作View的話熙涤,需要自己轉(zhuǎn)換到UI線程,非常繁瑣困檩,所以需要封裝祠挫。也有將OkHttp作為Volley底層Http實現(xiàn)的用法,發(fā)送請求悼沿、維護(hù)請求隊列用的是Volley等舔,實際的Http請求用的是OkHttp。
關(guān)于Volley和oOkHttp結(jié)合的Demo請戳煎蛋項目
如何使用
初始化
你可以在Application里面完成初始化糟趾,因為對OkHttp的封裝主要使用的是代理設(shè)計模式慌植,使用OkHttpProxy.getInstance()
可以獲取到單例客戶端甚牲,你可以像沒封裝之前一樣,設(shè)置任意的參數(shù)蝶柿,比如下面就設(shè)置超時時間和忽略HTTPS認(rèn)證丈钙。
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方法
你大多數(shù)情況下是和OkHttpProxy這個代理類打交道,而且OkHttpPlus支持鏈?zhǔn)秸{(diào)用交汤,內(nèi)部采用Builder設(shè)計模式雏赦,所以你可以像下面這樣使用
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的構(gòu)造函數(shù)中,你需要傳入一個解析器邀摆,OkHttpPlus內(nèi)部支持5種解析器纵顾,這可以解決你大部分的需求
- OkBaseParser,所有解析器的基類栋盹,不可直接使用
- OkBaseJsonParser施逾,所有JSON解析器的基類,你可以繼承它來定義自己的JSON解析
- OkJsonParser例获,JSON解析器汉额,支持JSONObject和JSONArray的解析,默認(rèn)使用GSON作為解析器
- OkTextParser榨汤,String解析器蠕搜,支持將結(jié)果以String方式輸出
- OkFileParser,文件解析器收壕,支持將結(jié)果保存為文件妓灌,你可以用來下載文件,但是不支持較大文件下載
所以如果你想獲取一個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數(shù)據(jù)虫埂,你可以這樣
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());
}
});
當(dāng)然,如果你想自定義一個解析器圃验,也是完全可以的掉伏。
OkHttpPlus的解析器部分使用的是策略設(shè)計模式,所以你可以像下面這樣自定義一個解析策略澳窑,完成結(jié)果的解析
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;
}
}
}
然后就可以將返回結(jié)果解析為ArrayList<Joke>了
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方法使用類似斧散,你可以像下面這樣發(fā)送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());
}
});
你可能注意到了颅湘,在發(fā)送每個請求的時候,我都調(diào)用了tag()方法栗精,所以你可以在不需要的時候闯参,將請求取消掉瞻鹏。
@Override
protected void onDestroy() {
super.onDestroy();
OkHttpProxy.cancel(this);
}
下載
你可以像下面這樣下載一個文件,但是由于下載的內(nèi)容都在內(nèi)存中鹿寨,所以不支持大文件下載新博,否則會OOM
String desFileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
OkHttpProxy.download(URL_DOWMLOAD, new DownloadListener(desFileDir, "json.jar") {
@Override
public void onUIProgress(Progress progress) {
//當(dāng)下載資源長度不可知時,progress.getTotalBytes()為-1脚草,此時不能顯示下載進(jìn)度
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是有期限的馏慨,所以你需要在下面網(wǎng)址自己生成測試
/**
* 采用七牛上傳接口埂淮,Token有效期為12小時,若Token無效写隶,請在下面自行獲取
* Token生成網(wǎng)址 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());
}
});
}
靈感來源
本項目的靈感和部分代碼來自于下面兩個開源項目,謝謝他們的分享精神
尊重原創(chuàng)慕趴,轉(zhuǎn)載請注明:From 凱子哥 侵權(quán)必究痪蝇!