需求:
首先用一个抽象类用于回调
public abstract class ResultCallback {
public abstract void onError(Request request,Exception e);
public abstract void onSuccess(Object str);
}
oKHttp无论哪种方式请求都是创建OkHttpClient、Request和Call对象,然后在调用Call的enqueue()方法。
private volatile static oKHttpEngine mInstance;
private oKHttpEngine(){}
public static oKHttpEngine getInstance(){
if(mInstance == null){
synchronized (oKHttpEngine.class){
if(mInstance == null){
mInstance = new oKHttpEngine();
}
}
}
return mInstance;
}
使用单例设计模式,获取类的对象,由于是单例设计模式,所以无论对getInstance()调用多少次都只会创建一个对象
public void setHttpConfig(HttpConfig httpConfig){
this.httpConfig = httpConfig;
client = new OkHttpClient.Builder()
.connectTimeout(httpConfig.getConnectionTimeOut(), TimeUnit.SECONDS)
.readTimeout(httpConfig.getReadTmeOut(),TimeUnit.SECONDS)
.writeTimeout(httpConfig.getWriteTimeOut(),TimeUnit.SECONDS)
.proxy(Proxy.NO_PROXY)
.build();
mHandler = new Handler();
gson = new Gson();
}
创建oKHttpClient对象,并设置链接时间,读取时间等信息,此方法必须被调用。并创建Gson对象和Handler对象。
private Call execute(Request.Builder builder,Header[] h, ResultCallback resultCallback,String url){
//设置请求头信息
boolean hasUa = false;
if(h==null){
builder.header("Connection","close");
builder.header("Accept","*/*");
}else {
for (Util.Header header:h){
builder.header(header.getName(),header.getValue());
if(!hasUa&&header.getName().equals("User-Agent")){
hasUa = true;
}
}
}
if(!hasUa&&!TextUtils.isEmpty(httpConfig.getUserAgent())){
builder.header("User-Agent",httpConfig.getUserAgent());
}
Call call = client.newCall(builder.build());
dealResult(call,resultCallback,url);
return call;
}
首先设置请求头信息,通常不需要设置,通过build()方法创建Request对象,并且创建Call对象
private void dealResult(Call call, final ResultCallback resultCallback, final String url){
call.enqueue(new Callback() {
@Override
public void onFailure(Call call,IOException e) {
sendFailed(call.request(),resultCallback,e);
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if(resultCallback!=null){
try {
String str = response.body().string();
if(clazz!=null||clazzBean!=null){
JSONObject jsonObject = new JSONObject(str);
String strData = jsonObject.toString();
//用于解析JSON中的数组
if(info!=null){
JSONArray jsonArray = jsonObject.getJSONArray(info);
if(jsonArray.length()>0){
for(int i =0;i//用于解析JSON数据中去除数组的部分
if(clazzBean!=null){
Object o = gson.fromJson(strData,clazzBean);
sendSuccess(o,resultCallback);
}
}else {
sendSuccess(str,resultCallback);
}
} catch (IOException e) {
e.printStackTrace();
}catch (JSONException e){
e.printStackTrace();
}
}else {
try {
ResponseBody requestBody = ProgressHelper.withProgress(response.body(),progressListener);
BufferedSource bufferedSource = requestBody.source();
File file = new File(saveFilePath);
file.delete();
file.getParentFile().mkdirs();
file.createNewFile();
BufferedSink sink = Okio.buffer(Okio.sink(file));
bufferedSource.readAll(sink);
sink.flush();
bufferedSource.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
private void sendSuccess(final Object o, final ResultCallback resultCallback){
if(resultCallback!=null){
mHandler.post(new Runnable() {
@Override
public void run() {
resultCallback.onSuccess(o);
}
});
}
}
private void sendFailed(final Request request, final ResultCallback resultCallback, final Exception e){
mHandler.post(new Runnable() {
@Override
public void run() {
if(resultCallback!=null){
resultCallback.onError(request,e);
}else {
e.printStackTrace();
}
}
});
}
});
}
如果下载文件则不需要设置回调,故ResultCallback设置为null,这里上传和下载文件的监听使用的是开源库https://github.com/lizhangqu/CoreProgress,在请求数据时若返回的是JSON数据,首先解析JSON数组,然后解析非数组的部分。注意这里的数据解析在子线程中运行,当解析完毕后才把数据发送给主线程回调
get请求:
public void asyncGet(String url,Header[] h,ResultCallback resultCallback,Class clazz,Class clazzBean,String info){
this.clazz = clazz;
this.clazzBean = clazzBean;
this.info = info;
Request.Builder builder = new Request.Builder();
builder.url(url);
Call call = execute(builder,h,resultCallback,url);
add(url,call);
}
post请求:
public void post(String url, Header[] h, ResultCallback resultCallback, List list,Class clazz,Class clazzBean,String info){
if(list == null){
list = new ArrayList<>();
}
this.clazz = clazz;
this.clazzBean = clazzBean;
this.info = info;
list.addAll(httpConfig.getComFiled());
FormBody.Builder form = new FormBody.Builder();
for(NameValue item:list){
form.add(item.getName(),item.getValue());
}
RequestBody requestBody = form.build();
Request.Builder builder = new Request.Builder();
builder.url(url);
builder.post(requestBody);
Call call = execute(builder,h,resultCallback,url);
add(url,call);
}
上传JSON:
public void jsonPost(String url,Header[] h,ResultCallback resultCallback,Map<String,String> map,Class clazz,Class clazzBean,String info){
this.info = info;
this.clazzBean = clazzBean;
this.clazz = clazz;
String str = gson.toJson(map);
MediaType Json = MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(Json,str);
Request.Builder builder = new Request.Builder();
builder.url(url);
builder.post(requestBody);
Call call = execute(builder,h,resultCallback,url);
add(url,call);
}
上传文件:
public void postFile(String url, Header[] h, ResultCallback resultCallback, Set files, Class clazz, Class clazzBean, String info, String key, ProgressUIListener progressUIListener){
this.clazz = clazz;
this.clazzBean = clazzBean;
this.info = info;
MediaType mediaType = MediaType.parse("application/octet-stream");
MultipartBody.Builder mBuilder = new MultipartBody.Builder();
mBuilder.setType(MultipartBody.FORM);
if(files!=null){
for(File file:files){
mBuilder.addFormDataPart(key,file.getName(),RequestBody.create(mediaType,file));
}
}
RequestBody requestBody = null;
if(progressUIListener!=null){//需要回调上传进度
requestBody = ProgressHelper.withProgress(mBuilder.build(),progressUIListener);
}else {//不需要回调上传进度
requestBody = mBuilder.build();
}
Request.Builder builder = new Request.Builder();
builder.url(url);
builder.post(requestBody);
Call call = execute(builder,h,resultCallback,url);
add(url,call);
}
下载文件:
public void downloadFile(String url,Header[] h,ResultCallback resultCallback,String saveFilePath,ProgressUIListener progressUIListener){
this.progressListener = progressUIListener;
this.saveFilePath = saveFilePath;
Request.Builder builder = new Request.Builder();
builder.url(url);
Call call = execute(builder,h,resultCallback,url);
add(url,call);
}
private void add(String url,Call call){
if(!TextUtils.isEmpty(url)){
if(url.contains("?")){
url = url.substring(0,url.indexOf("?"));
}
cancel(url);
map.put(url,call);
}
}
private void cancel(String url){
Call call = map.remove(url);
if(call!=null){
call.cancel();
}
}
首先将URL和Call对象添加到map集合中,当从map中取出Call不为null时则取消请求,在第一次请求时,首先从集合中取出Call对象,由于是第一次请求故Call为null,当进行第二次相同的请求时,此时从集合中取出的是第一次请求的Call对象,故调用cancel()方法取消该请求。
全部代码OKHTTP封装2