okhttp一個處理網絡請求的開源項目,是安卓端最火熱的輕量級架構,由移動支付Square公司貢獻,用于替代HttpUrlConnection和Apache HttpClient。
目前已經更新到了okhttp3,相對與之前的2變動的還是比較的大,
okhttp直接newOkHttpClient,而okhttp3中提供了Builder,使用了建立者設計模式,
OkHttpClient參數的配置:之前參數可以直接OkHttpClient.setConnectTimeout()設定,現在OkHttpClient使用建立者模式,需要在OkHttpClient.Builder上設定可配置的參數:
new OkHttpClient.Builder().connectTimeout();
okhttp調用OkHttpClient的setCookieHandler方法,CookieHandler 的子類CookieManager實作了cookie的具體管理方法,okhttp3中已經沒有setCookieHandler方法了,而改成了cookieJar,需要在OkHttpClient的Builder的cookieJar方法中設定。
post請求:
okhttp使用MultipartBuilder,FormEncodingBuilder建構post消息體,最終建構出來的都是RequestBody,而okhttp3增加了RequestBody的子類,構造器放到了RequestBody的子類中,MultipartBody.Builder既可以添加表單資料,也可以添加檔案等二進制資料。
回調方法Callback在3.0之後變為了:void onFailure(Call call, IOException e),void onResponse(Call call, Response response)。
導入:
compile 'com.squareup.okhttp3:okhttp:3.3.0'
簡單使用方法:
首先,如果要設定設定逾時時間和緩存,要通過OkHttpClient.Builder來設定,
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
OkHttpClient okHttpClient=builder.build();
get請求:
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println(response.body().string());
}
});
response的body有很多種輸出方法,string()隻是其中之一,注意是string()不是toString()。如果是下載下傳檔案就是response.body().bytes()。
另外可以根據response.code()擷取傳回的狀态碼。
post請求:
post送出普通的表單:如登入..
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("鍵", "值")
.add("鍵", "值")
.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {...}
RequestBody的資料格式都要指定Content-Type,常見的有三種:
application/x-www-form-urlencoded 資料是個普通表單
multipart/form-data 資料裡有檔案
application/json 資料是個json
上邊的普通表單并沒有指定Content-Type,這是因為FormBody繼承了RequestBody,它已經指定了資料類型為application/x-www-form-urlencoded。
post送出json資料:
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, "你的json資料");
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {...}
post上傳檔案:
先定義上傳檔案類型:
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("/sdcard/xxx.txt");
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
call.enqueue(new Callback() {...}
post上傳檔案并傳入其他類型的字段:
public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("/sdcard/xxx.txt");
RequestBody requestBody = new MultipartBody.Builder()
.addFormDataPart("token","token")
.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
call.enqueue(new Callback() {...}
異步下載下傳:
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File("/sdcard/xx.txt"));
byte[] buffer = new byte[2048];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
上面的都為異步請求,當然也支援同步的方式,同步的隻要調用 call.execute()就可以了。
okhttp3的簡單封裝:
public class OkHttpClientManager {
private static OkHttpClientManager mInstance;
private OkHttpClient mOkHttpClient;
private Handler mDelivery;
private Gson mGson;
private OkHttpClientManager()
{
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
okHttpClient.connectTimeout(5, TimeUnit.SECONDS);
okHttpClient.readTimeout(5, TimeUnit.SECONDS);
okHttpClient.cookieJar(new CookieJar() {
private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put(url, cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
return null;
}
});
mOkHttpClient=okHttpClient.build();
mDelivery = new Handler(Looper.getMainLooper());
mGson = new Gson();
}
public static OkHttpClientManager getInstance()
{
if (mInstance == null)
{
synchronized (OkHttpClientManager.class)
{
if (mInstance == null)
{
mInstance = new OkHttpClientManager();
}
}
}
return mInstance;
}
/**
* 異步的get請求
*
* @param url
* @param callback
*/
private void _getAsyn(String url, final ResultCallback callback)
{
final Request request = new Request.Builder()
.url(url)
.build();
deliveryResult(callback, request);
}
/**
* 異步的post請求
*
* @param url
* @param callback
* @param params
*/
private void _postAsyn(String url, final ResultCallback callback, Param... params)
{
Request request = buildPostRequest(url, params);
deliveryResult(callback, request);
}
/**
* 異步的post請求
*
* @param url
* @param callback
* @param params
*/
private void _postAsyn(String url, final ResultCallback callback, Map<String, String> params)
{
Param[] paramsArr = map2Params(params);
Request request = buildPostRequest(url, paramsArr);
deliveryResult(callback, request);
}
private Param[] map2Params(Map<String, String> params)
{
if (params == null) return new Param[0];
int size = params.size();
Param[] res = new Param[size];
Set<Map.Entry<String, String>> entries = params.entrySet();
int i = 0;
for (Map.Entry<String, String> entry : entries)
{
res[i++] = new Param(entry.getKey(), entry.getValue());
}
return res;
}
//*************對外公布的方法************
//異步get請求
public static void getAsyn(String url, ResultCallback callback)
{
getInstance()._getAsyn(url, callback);
}
//異步的post請求
public static void postAsyn(String url, final ResultCallback callback, Param... params)
{
getInstance()._postAsyn(url, callback, params);
}
//異步的post請求
public static void postAsyn(String url, final ResultCallback callback, Map<String, String> params)
{
getInstance()._postAsyn(url, callback, params);
}
private void deliveryResult(final ResultCallback callback, Request request)
{
mOkHttpClient.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e) {
sendFailCallback(callback,e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try
{
final String string = response.body().string();
if (callback.mType == String.class)
{
sendSuccessCallBack(callback,string);
} else
{
Object o = mGson.fromJson(string, callback.mType);
sendSuccessCallBack(callback,string);
}
} catch (IOException e)
{
sendFailCallback(callback,e);
} catch (com.google.gson.JsonParseException e)//Json解析的錯誤
{
sendFailCallback(callback,e);
}
}
});
}
private void sendFailCallback(final ResultCallback callback, final Exception e) {
mDelivery.post(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onFailure(e);
}
}
});
}
private void sendSuccessCallBack(final ResultCallback callback, final Object obj) {
mDelivery.post(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onSuccess(obj);
}
}
});
}
private Request buildPostRequest(String url, Param[] params)
{
if (params == null)
{
params = new Param[0];
}
FormBody.Builder formBodyBuilder = new FormBody.Builder();
for (Param param : params)
{
formBodyBuilder.add(param.key, param.value);
}
RequestBody requestBody = formBodyBuilder.build();
return new Request.Builder()
.url(url)
.post(requestBody)
.build();
}
public static abstract class ResultCallback<T>
{
Type mType;
public ResultCallback()
{
mType = getSuperclassTypeParameter(getClass());
}
static Type getSuperclassTypeParameter(Class<?> subclass)
{
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class)
{
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
/**
* 請求成功回調
* @param response
*/
public abstract void onSuccess(T response);
/**
* 請求失敗回調
* @param e
*/
public abstract void onFailure(Exception e);
}
/**
* post請求參數類
*/
public static class Param
{
public Param()
{
}
public Param(String key, String value)
{
this.key = key;
this.value = value;
}
String key;
String value;
}
}