Android 一個改善的okHttp封裝庫
轉載請標明出處:
http://blog.csdn.net/lmj623565791/article/details/49734867;
本文出自:【張鴻洋的博客】
一、概述
之前寫了篇Android OkHttp完全解析 是時候來了解OkHttp了,其實主要是作為okhttp的普及文章,當然里面也簡單封裝了工具類,沒想到關注和使用的人還挺多的,由于這股熱情,該工具類中的方法也是劇增,各種重載方法,以致于使用起來極不方便,實在慚愧。
于是,在這個周末,抽點時間對該工具類,進行了重新的拆解與編寫,順便完善下功能,盡可能的提升其使用起來的方便性和易擴展性。
標題的改善,也是指的是對于我之前的代碼進行改善。
如果你對okhttp不了解,可以通過Android OkHttp完全解析 是時候來了解OkHttp了進行了解。
ok,那么目前,該封裝庫志支持:
- 一般的get請求
- 一般的post請求
- 基于Http的文件上傳
- 文件下載
- 上傳下載的進度回調
- 加載圖片
- 支持請求回調,直接返回對象、對象集合
- 支持session的保持
- 支持自簽名網站https的訪問,提供方法設置下證書就行
- 支持取消某個請求
源碼地址:https://github.com/hongyangAndroid/okhttp-utils
引入:
-
Android Studio
使用前,對于Android Studio的用戶,可以選擇添加:
compile project(':okhttputils')或者
compile 'com.zhy:okhttputils:2.0.0'
-
Eclipse
自行copy源碼。
二、基本用法
目前基本的用法格式為:
OkHttpUtils
.get()
.url(url)
.addParams("username", "hyman")
.addParams("password", "123")
.build()
.execute(callback); 通過鏈式去根據自己的需要添加各種參數,最后調用execute(callback)進行執行,傳入callback則代表是異步。如果單純的execute()則代表同步的方法調用。
可以看到,取消了之前一堆的get重載方法,參數也可以進行靈活的選擇了。
下面簡單看一下,全部的用法:
(1)GET請求
String url = "http://www.csdn.net/";
OkHttpUtils
.get()
.url(url)
.addParams("username", "hyman")
.addParams("password", "123")
.build()
.execute(new StringCallback()
{
@Override
public void onError(Request request, Exception e)
{
}
@Override
public void onResponse(String response)
{
}
}); (2)POST請求
OkHttpUtils
.post()
.url(url)
.addParams("username", "hyman")
.addParams("password", "123")
.build()
.execute(callback); (3)Post String
OkHttpUtils
.postString()
.url(url)
.content(new Gson().toJson(new User("zhy", "123")))
.build()
.execute(new MyStringCallback()); 將string作為請求體傳入到服務端,例如json字符串。
(4)Post File
OkHttpUtils
.postFile()
.url(url)
.file(file)
.build()
.execute(new MyStringCallback()); 將file作為請求體傳入到服務端.
(5)基于POST的文件上傳(類似web上的表單)
OkHttpUtils.post()//
.addFile("mFile", "messenger_01.png", file)//
.addFile("mFile", "test1.txt", file2)//
.url(url)
.params(params)//
.headers(headers)//
.build()//
.execute(new MyStringCallback()); (6)下載文件
OkHttpUtils//
.get()//
.url(url)//
.build()//
.execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "gson-2.2.1.jar")//
{
@Override
public void inProgress(float progress)
{
mProgressBar.setProgress((int) (100 * progress));
}
@Override
public void onError(Request request, Exception e)
{
Log.e(TAG, "onError :" + e.getMessage());
}
@Override
public void onResponse(File file)
{
Log.e(TAG, "onResponse :" + file.getAbsolutePath());
}
}); (7)顯示圖片
OkHttpUtils
.get()//
.url(url)//
.build()//
.execute(new BitmapCallback()
{
@Override
public void onError(Request request, Exception e)
{
mTv.setText("onError:" + e.getMessage());
}
@Override
public void onResponse(Bitmap bitmap)
{
mImageView.setImageBitmap(bitmap);
}
}); 哈,目前來看,清晰多了。
三、對于上傳下載的回調
new Callback<?>()
{
//...
@Override
public void inProgress(float progress)
{
//use progress: 0 ~ 1
}
} 對于傳入的callback有個inProgress方法,需要拿到進度直接復寫該方法即可。
四、對于自動解析為實體類
目前去除了Gson的依賴,提供了自定義Callback的方式,讓用戶自己去解析返回的數據,目前提供了StringCallback,FileCallback,BitmapCallback 分別用于返回string,文件下載,加載圖片。
當然如果你希望解析為對象,你可以:
public abstract class UserCallback extends Callback<User>
{
//非UI線程,支持任何耗時操作
@Override
public User parseNetworkResponse(Response response) throws IOException
{
String string = response.body().string();
User user = new Gson().fromJson(string, User.class);
return user;
}
} 自己使用自己喜歡的Json解析庫完成即可。
解析成List<User>,則如下:
public abstract class ListUserCallback extends Callback<List<User>>
{
@Override
public List<User> parseNetworkResponse(Response response) throws IOException
{
String string = response.body().string();
List<User> user = new Gson().fromJson(string, List.class);
return user;
}
} 五、對于https單向認證
非常簡單,拿到xxx.cert的證書。
然后調用
OkHttpUtils.getInstance()
.setCertificates(inputstream); 建議使用方式,例如我的證書放在assets目錄:
/**
* Created by zhy on 15/8/25.
*/
public class MyApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate();
try
{
OkHttpUtils
.getInstance()
.setCertificates(getAssets().open("aaa.cer"),
getAssets().open("server.cer"));
} catch (IOException e)
{
e.printStackTrace();
}
}
} 即可。別忘了注冊Application。
注意:如果https網站為權威機構頒發的證書,不需要以上設置。自簽名的證書才需要。
六、配置
(1)全局配置
可以在Application中,通過:
OkHttpClient client = OkHttpUtils.getInstance().getOkHttpClient();
然后調用client的各種set方法。
例如:
client.setConnectTimeout(100000, TimeUnit.MILLISECONDS);
(2)為單個請求設置超時
比如涉及到文件的需要設置讀寫等待時間多一點。
OkHttpUtils
.get()//
.url(url)//
.tag(this)//
.build()//
.connTimeOut(20000)
.readTimeOut(20000)
.writeTimeOut(20000)
.execute() 調用build()之后,可以隨即設置各種timeOut.
(3)取消單個請求
RequestCall call = OkHttpUtils.get().url(url).build(); call.cancel();
(4)根據tag取消請求
目前對于支持的方法都添加了最后一個參數Object tag,取消則通過OkHttpUtils.cancelTag(tag)執行。
例如:在Activity中,當Activity銷毀取消請求:
OkHttpUtils
.get()//
.url(url)//
.tag(this)//
.build()//
@Override
protected void onDestroy()
{
super.onDestroy();
//可以取消同一個tag的
OkHttpUtils.cancelTag(this);//取消以Activity.this作為tag的請求
} 比如,當前Activity頁面所有的請求以Activity對象作為tag,可以在onDestory里面統一取消。
七、淺談封裝
其實整個封裝的過程比較簡單,這里簡單描述下,對于okhttp一個請求的流程大致是這樣的:
//創建okHttpClient對象
OkHttpClient mOkHttpClient = new OkHttpClient();
//創建一個Request
final Request request = new Request.Builder()
.url("https://github.com/hongyangAndroid")
.build();
//new call
Call call = mOkHttpClient.newCall(request);
//請求加入調度
call.enqueue(new Callback()
{
@Override
public void onFailure(Request request, IOException e)
{
}
@Override
public void onResponse(final Response response) throws IOException
{
//String htmlStr = response.body().string();
}
}); 其中主要的差異,其實就是request的構建過程。
我對Request抽象了一個類:OkHttpRequest
public abstract class OkHttpRequest
{
protected RequestBody requestBody;
protected Request request;
protected String url;
protected String tag;
protected Map<String, String> params;
protected Map<String, String> headers;
protected OkHttpRequest(String url, String tag,
Map<String, String> params, Map<String, String> headers)
{
this.url = url;
this.tag = tag;
this.params = params;
this.headers = headers;
}
protected abstract Request buildRequest();
protected abstract RequestBody buildRequestBody();
protected void prepareInvoked(ResultCallback callback)
{
requestBody = buildRequestBody();
requestBody = wrapRequestBody(requestBody, callback);
request = buildRequest();
}
protected RequestBody wrapRequestBody(RequestBody requestBody, final ResultCallback callback)
{
return requestBody;
}
public void invokeAsyn(ResultCallback callback)
{
prepareInvoked(callback);
mOkHttpClientManager.execute(request, callback);
}
// other common methods
} 一個request的構建呢,我分三個步驟:buildRequestBody , wrapRequestBody ,buildRequest這樣的次序,當以上三個方法沒有問題時,我們就拿到了request,然后執行即可。
但是對于不同的請求,requestBody以及request的構建過程是不同的,所以大家可以看到buildRequestBody ,buildRequest為抽象的方法,也就是不同的請求類,比如OkHttpGetRequest、OkHttpPostRequest等需要自己去構建自己的request。
對于wrapRequestBody方法呢,可以看到它默認基本屬于空實現,主要是因為并非所有的請求類都需要復寫它,只有上傳的時候呢,需要回調進度,需要對requestBody進行包裝,所以這個方法類似于一個鉤子。
其實這個過程有點類似模板方法模式,有興趣可以看看一個短篇介紹設計模式 模版方法模式 展現程序員的一天 .
對于更加詳細的用法,可以查看github上面的readme,以及demo,目前demo包含:

對于上傳文件的兩個按鈕,需要自己搭建服務器,其他的按鈕可以直接測試。
最后,由于本人水平有限,以及時間比較倉促~~發現問題,歡迎提issue,我會抽時間解決。 have a nice day ~
歡迎關注我的微博:
http://weibo.com/u/3165018720
群號:514447580,歡迎入群
微信公眾號:hongyangAndroid
(歡迎關注,第一時間推送博文信息)
來自: http://blog.csdn.net/lmj623565791/article/details/49734867
