? ? ? ?最近實際項目需要處理網(wǎng)絡(luò)請求(一般是個app都會有的),于是接觸了okhttp,目前也就剛剛會使用的程度,不過還是總結(jié)一下吧,個人學(xué)習(xí)的理解不喜勿噴哈。
? ? ? ?介紹就不多說了,它就是一個Android用來請求網(wǎng)絡(luò)的第三方類庫,開源的,是目前非?;鸬囊豢钶p量級HTTP框架,由Square公司開發(fā)。
? ? ? ? 好了廢話少說,下面直接上使用說明,我使用的是OKHttp3,就以O(shè)KHttp3為例子,因為是提取出來的單獨demo,可能有的變量類名沒有完全修改對,可能有名字不對的低級錯誤歡迎指正。
導(dǎo)入方法
在gradle里導(dǎo)入就行了
dependencies里添加這一行完成導(dǎo)入
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
GET方法
同步:
public void getOkHttpByExeCute(final String url){
? ? ? ? new Thread(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? //創(chuàng)建OkHttpClient實例
? ? ? ? ? ? ? ? ? ? OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .writeTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .build();
? ? ? ? ? ? ? ? ? ? //創(chuàng)建Request
? ? ? ? ? ? ? ? ? ? Request request = new Request.Builder().url(url).build();
? ? ? ? ? ? ? ? ? ? Call call = okHttpClient.newCall(request);
? ? ? ? ? ? ? ? ? ? //獲取Response響應(yīng)
? ? ? ? ? ? ? ? ? ? final Response response = call.execute();
? ? ? ? ? ? ? ? ? ? if (response.isSuccessful()) {
? ? ? ? ? ? ? ? ? ? ? ? //UI操作在回到主線程執(zhí)行
? ? ? ? ? ? ? ? ? ? ? ? runOnUiThread(new Runnable() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(mContext,response.code() + response.message() + "",Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }catch (Exception e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? }
異步:
異步請求不需要開啟新線程,只需要將回調(diào)在子線程中執(zhí)行
public void getOkHttpByEnqueue(final String url,final Context context){
try {
//創(chuàng)建OkHttpClient實例
? ? ? ? OkHttpClient okHttpClient =new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS)
.build();
? ? ? ? //創(chuàng)建Request
? ? ? ? Request request =new Request.Builder().url(url).build();
? ? ? ? Call call = okHttpClient.newCall(request);
? ? ? ? //回調(diào)
? ? ? ? call.enqueue(new Callback() {
@Override
? ? ? ? ? ? public void onFailure(Call call, IOException e) {
}
@Override
? ? ? ? ? ? public void onResponse(Call call, Response response)throws IOException {
if(response.isSuccessful()){
//本部分在子線程執(zhí)行
//UI操作在回到主線程執(zhí)行
? ? ? ? ? ? ? ? ? ? final Response response2 = response;
? ? ? ? ? ? ? ? ? ? runOnUiThread(new Runnable() {
@Override
? ? ? ? ? ? ? ? ? ? ? ? public void run() {
Toast.makeText(context,response2.code() +response2.message() +"",Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? ? ? }
});
? ? ? ? ? ? ? ? }
}
});
? ? }catch (Exception e) {
e.printStackTrace();
? ? }
}
POST方法
post鍵值對
//post異步請求發(fā)送鍵值對
public static void PostMapByEnqueue (String url, Map map, Callback callback,final Context context) {
FormBody.Builder builder =new FormBody.Builder();
? ? //遍歷集合
? ? for (String key : map.keySet()) {
builder.add(key, map.get(key));
? ? }
//創(chuàng)建Request
? ? Request request =new Request.Builder().url(url).post(builder.build()).build();
? ? Call call =getOkHttpClient().newCall(request);
? ? call.enqueue(new Callback() {
@Override
? ? ? ? public void onFailure(Call call, IOException e) {
}
@Override
? ? ? ? public void onResponse(Call call, Response response)throws IOException {
if(response.isSuccessful()){
//子線程執(zhí)行
//UI操作在回到主線程執(zhí)行
? ? ? ? ? ? ? ? final Response response2 = response;
? ? ? ? ? ? ? ? runOnUiThread(new Runnable() {
@Override
? ? ? ? ? ? ? ? ? ? public void run() {
Toast.makeText(context,response2.code() +response2.message() +"",Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? }
});
? ? ? ? ? ? }
}
});
}
post JSON數(shù)據(jù)
//post異步請求發(fā)送json數(shù)據(jù)
public static void PostJson(String url, String string, Callback callback,final Context context) {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");//數(shù)據(jù)類型為json格式,
? ? RequestBody body = RequestBody.create(JSON, string);
? ? //創(chuàng)建Request
? ? Request request =new Request.Builder().url(url).post(body).build();
? ? Call call =getOkHttpClient().newCall(request);
? ? call.enqueue(new Callback() {
@Override
? ? ? ? public void onFailure(Call call, IOException e) {
}
@Override
? ? ? ? public void onResponse(Call call, Response response)throws IOException {
if(response.isSuccessful()){
//子線程執(zhí)行
//UI操作在回到主線程執(zhí)行
? ? ? ? ? ? ? ? final Response response2 = response;
? ? ? ? ? ? ? ?runOnUiThread(new Runnable() {
@Override
? ? ? ? ? ? ? ? ? ? public void run() {
Toast.makeText(context,response2.code() +response2.message() +"",Toast.LENGTH_SHORT).show();
? ? ? ? ? ? ? ? ? ? }
});
? ? ? ? ? ? }
}
});
}
okhttp實現(xiàn)下載功能
這一步在回調(diào)Callback中執(zhí)行,原理理解同上,將onResponse中的子線程操作具體為下載就行了,下載功能原理是從Response中獲取輸入流對象實現(xiàn)文件下載
//Okhttp實現(xiàn)下載功能(json數(shù)據(jù)同理)
public static void download(String url, Map map, Callback callback, final Context context, final String pathStr) {
FormBody.Builder builder =new FormBody.Builder();
? ? //遍歷集合
? ? for (String key : map.keySet()) {
builder.add(key, map.get(key));
? ? }
//創(chuàng)建Request
? ? Request request =new Request.Builder().url(url).post(builder.build()).build();
? ? Call call =getOkHttpClient().newCall(request);
? ? call.enqueue(new Callback() {
@Override
? ? ? ? public void onFailure(Call call, IOException e) {
}
@Override
? ? ? ? public void onResponse(Call call, Response response)throws IOException {
if(response.isSuccessful()){
//子線程執(zhí)行
? ? ? ? ? ? ? ? try{
InputStream? is = response.body().byteStream();// 在Response中獲取輸入流對象
? ? ? ? ? ? ? ? ? ? File dir =new File(pathStr);
? ? ? ? ? ? ? ? ? ? if (!dir.exists()){
dir.mkdirs();
? ? ? ? ? ? ? ? ? ? }
File file =new File(dir, pathStr);
? ? ? ? ? ? ? ? ? ? FileOutputStream? fos =new FileOutputStream(file);
? ? ? ? ? ? ? ? ? ? byte[] buf =new byte[1024*8];
? ? ? ? ? ? ? ? ? ? int len =0;
? ? ? ? ? ? ? ? ? ? while ((len = is.read(buf)) != -1){
fos.write(buf, 0, len);
? ? ? ? ? ? ? ? ? ? }
fos.flush();//file下載完成
? ? ? ? ? ? ? ? }catch (Exception e) {
e.printStackTrace();
? ? ? ? ? ? ? ? }
}
}
});
}
進(jìn)一步的封裝
實際開發(fā)中,肯定一堆不同的地方要用到網(wǎng)絡(luò)請求,我們不可能每一次都寫一個post,get請求。為了進(jìn)一步方便使用,可以考慮封裝成一個工具類,我的思路如下:
首先定義獲取的數(shù)據(jù)類,ResponseResult
public class ResponseResult {
private int status;
? ? private Stringmsg;
? ? private Objectdata;
? ? public ResponseResult(int status, String msg, Object data) {
this.status = status;
? ? ? ? this.msg = msg;
? ? ? ? this.data = data;
? ? }
public ResponseResult() {
}
public int getStatus() {
return status;
? ? }
public void setStatus(int status) {
this.status = status;
? ? }
public StringgetMsg() {
return msg;
? ? }
public void setMsg(String msg) {
this.msg = msg;
? ? }
public ObjectgetData() {
return data;
? ? }
public void setData(Object data) {
this.data = data;
? ? }
}
然后自定義回調(diào)類,ResponseCallBack
在這里為了更好轉(zhuǎn)換返回的json數(shù)據(jù),我們需要導(dǎo)入fastjson這個類庫,解析json非常方便實用,當(dāng)然這就又是另一部分內(nèi)容了,這里就一筆帶過不做詳細(xì)介紹。
導(dǎo)入方法:
gradle里加入這一行完成導(dǎo)入
implementation"com.alibaba:fastjson:1.2.47"
好的回來繼續(xù)寫ResponseCallBack回調(diào)
public abstract class ResponseCallBack Callback {
private Handlerhandler = HttpRequestHandler.getInstance().getHandler();
? ? //主線程處理
? ? public abstract void onUi(HttpResult result);
? ? //主線程處理
? ? public abstract void onFailed(Call call, IOException e);
? ? @Override
? ? public void onFailure(final Call call, final IOException e) {
handler.post(new Runnable() {
@Override
? ? ? ? ? ? public void run() {
onFailed(call, e);
? ? ? ? ? ? }
});
? ? }
@Override
? ? public void onResponse(Call call, Response response)throws IOException {
final String result = response.body().string();
? ? ? ? handler.post(new Runnable() {
@Override
? ? ? ? ? ? public void run() {
onUi(JSON.parseObject(result, ResponseResult .class));
? ? ? ? ? ? }
});
? ? }
}
接下來寫重點,okhttp的工具類:OkHttpUtil
public class OkHttpUtil {
private static OkHttpUtil okHttpUtil =null;
? ? private OkHttpUtil() {
}
public static OkHttpUtil?getInstance() {
if (okHttpUtil ==null) {
//加同步安全
? ? ? ? ? ? synchronized (OkHttpUtil.class) {
if (okHttpUtil ==null) {
okHttpUtil =new OkHttpUtil();
? ? ? ? ? ? ? ? }
}
}
return okHttpUtil;
? ? }
private static OkHttpClient okHttpClient =null;
? ? public synchronized static OkHttpClient getOkHttpClient() {
if (okHttpClient ==null) {
okHttpClient =new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS)
.build();
? ? ? ? }
return okHttpClient;
? ? }
private static Handler mHandler =null;
? ? public synchronized static Handler getHandler() {
if (mHandler ==null) {
mHandler =new Handler();
? ? ? ? }
return mHandler;
? ? }
public static void doPost(String url, Map<String, String> map, Callback callback) {
FormBody.Builder builder =new FormBody.Builder();
? ? ? ? //遍歷集合
? ? ? ? for (String key : map.keySet()) {
builder.add(key, map.get(key));
? ? ? ? }
//創(chuàng)建Request
? ? ? ? Request request =new Request.Builder().url(url).post(builder.build()).build();
? ? ? ? Call call =getOkHttpClient().newCall(request);
? ? ? ? call.enqueue(callback);
? ? }
public static void doPost(String url, String string, Callback callback) {
MediaType JSON = MediaType.parse("application/json; charset=utf-8");//數(shù)據(jù)類型為json格式,
? ? ? ? RequestBody body = RequestBody.create(JSON, string);
? ? ? ? //創(chuàng)建Request
? ? ? ? Request request =new Request.Builder().url(url).post(body).build();
? ? ? ? Call call =getOkHttpClient().newCall(request);
? ? ? ? call.enqueue(callback);
? ? }
}
最后是使用,這里只舉post鍵值對的例子
private static int GET_OK = 0//獲取數(shù)據(jù)成功,實際數(shù)值根據(jù)項目定
public void getHttpData(String key,String value,String url){
final Map map =new HashMap();
? ? map.put(key, value);
? ? OkHttpUtil.getInstance().doPost(url, map, new ResponseCallBack() {
@Override
? ? ? ? public void onUi(ResponseResult result) {
if (result.getStatus() ==GET_OK) {
//主線程執(zhí)行操作
? ? ? ? ? ? }
}
@Override
? ? ? ? public void onFailed(Call call, IOException e) {
//主線程執(zhí)行操作
? ? ? ? }
});
}
封裝完成,收工~