本文主要介绍Android OkHttp的完整分析,现在就分享给大家,给大家一个参考。来和边肖一起看看吧。
一、概述
最近在群里听到各种关于okhttp的话题,可见okhttp的口碑不错。另外,谷歌似乎在6.0版本中删除了HttpClient的相关API,所以对这种行为不做评论。为了更好的应对网络访问,学习okhttp是相当必要的。本博客首先介绍okhttp的简单使用,主要包括:
常规获取请求
一般员额要求
基于Http的文件上传
下载文件
加载图片
支持回调直接返回对象和对象集合。
支持会话的维护
最后,对上述功能进行封装。完整封装类的地址见:http://xiazai.jb51.net/201611/yuanma/okhttputils-master jb51 . zip。
在使用之前,Android Studio的用户可以选择添加:
编译“com . square up . ok http:ok http:2 . 4 . 0”
或者Eclipse用户可以下载最新的jarokhttp最新的jar,并添加依赖项来使用它。
注意:okhttp内部依赖于okio。别忘了同时导入okio:
gradle:编译“com.squareup.okio:okio:1.5.0”
最新的罐子地址:okio最新的罐子
二、使用教程
(一)Http Get
对于web加载库,最常见的是http get请求,比如获取一个网页的内容。
//创建一个okHttpClient对象
OkHttpClient mOkHttpClient=new OkHttpClient();
//创建请求
最终请求请求=新请求。构建器()。URL(' https://github . com/hongyangAndroid ')。build();
//新呼叫
Call call=mOkHttpClient.newCall(请求);
//请求加入计划
call.enqueue(新回调()
{
@覆盖
public void onFailure(请求请求,IOException e)
{
}
@覆盖
public void onResponse(最终响应Response)抛出IOException
{
//String htmlStr=response.body()。string();
}
});
1.以上是发送get请求的步骤。首先,用至少一个url作为参数构造一个请求对象。当然,你可以设置更多的参数如:头,方法等。通过请求。建设者
2.然后通过请求的对象构造一个调用对象,类似于把你的请求封装成一个任务。既然是任务,就会有execute()和cancel()之类的方法。
3.最后,我们希望以异步的方式执行请求,所以我们调用call.enqueue,将调用添加到调度队列中,然后等待任务完成,我们可以在回调中得到结果。
看到这里,你会发现整体写的还是比较长的,所以一定要做封装。否则,像这样写每个请求会害死你的。
ok,需要注意几点:
1.onresponse回调的参数是response。一般来说,比如我们想获取返回的字符串,可以通过response.body()来获取。string();如果要获取返回的二进制字节数组,调用response.body()。bytes();如果希望获得返回的inputStream,请调用response.body()。字节流()
看到这里,您可能会惊讶,您仍然可以获得返回的inputStream。看到这里,你至少可以意识到一件事。这里支持大文件下载。有了inputStream,我们可以通过IO写文件。但是也说明了一个问题,onResponse执行的线程不是UI线程。是的,如果你想操作控件,你仍然需要使用handler等。例如:
@覆盖
public void onResponse(最终响应Response)抛出IOException
{
最终字符串res=response.body()。string();
runOnUiThread(新的Runnable()
{
@覆盖
公共无效运行()
{
MTV . settext(RES);
}
});
}
2.我们在这里异步执行,当然也支持阻塞方法。上面我们也说过,调用有一个execute()方法。还可以通过返回响应来直接调用call.execute()。
-
(2) Http Post携带参数
看来上面的简单的得到请求,基本上整个的用法也就掌握了,比如邮政携带参数,也仅仅是请求的构造的不同。
request request=buildMultipartFormRequest(
url,新文件[]{文件},新字符串[]{fileKey},null);
FormEncodingBuilder builder=new FormEncodingBuilder();
builder.add('username ','张鸿洋');
请求请求=新请求。构建器()。网址(网址)。post(builder.build())。build();
mOkHttpClient.newCall(请求)。排队(新回调(){ });
大家都清楚,发布的时候,参数是包含在请求体中的;所以我们通过FormEncodingBuilder。添加多个线键值对,然后去构造请求体,最后完成我们请求的构造。
后面的就和上面一样了。
-
(三)基于超文本传送协议(超文本传输协议的缩写)的文件上传
接下来我们在介绍一个可以构造请求主体的建筑商,叫做多生成器。当我们需要做类似于表单上传的时候,就可以使用它来构造我们的请求主体。
文件File=新文件(环境。getexternalstrauredirectory(),' balabala。MP4’);
请求正文文件正文=请求正文。创建(媒体类型。parse(' application/octet-stream '),file);
请求正文请求正文=新的多部分生成器()。类型(多生成器.表单)。addPart(Headers.of(
内容-处置,
表单数据;name='用户名''),
RequestBody.create(空,张鸿洋'))。addPart(Headers.of(
内容-处置,
表单数据;name=' mFile
filename='wjd.mp4 ' '),fileBody)。build();
请求请求=新请求。构建器()。网址(' http://192。168 .1 .103:8080/okhttp服务器/文件上传’)。发布(请求主体)。build();
Call call=mOkHttpClient.newCall(请求);
调用.入队(新回调()
{
//.
});
上述代码向服务器传递了一个键值对用户名:张鸿洋和一个文件。我们通过多生成器的添加零件方法可以添加键值对或者文件。
其实类似于我们拼接模拟浏览器行为的方式,如果你对这块不了解,可以参考:从原理角度解析Android (Java) http文件上传
好吧,对于我们最开始的目录还剩下图片下载,文件下载;这两个一个是通过回调的反应拿到字节[]然后译成图片;文件下载,就是拿到输入流做写文件操作,我们这里就不赘述了。
接下来我们主要看如何封装上述的代码。
-
三、封装
由于按照上述的代码,写多个请求肯定包含大量的重复代码,所以我希望封装后的代码调用是这样的:
(一)使用
1.一般的得到请求
OkHttpClientManager。get asyn(' https://www。百度一下。com),新建OkHttpClientManager .ResultCallbackString()
{
@覆盖
公共void onError(请求请求,异常e)
{
e。printstacktrace();
}
@覆盖
公共响应时无效(字符串u)
{
MTV。settext(u);//注意这里是用户界面线程
}
});
对于一般的请求,我们希望给个url,然后回收里面直接操作控件。
2.文件上传且携带参数
我们希望提供一个方法,传入url,参数,文件,回调即可。
okhttpclientmanager。发布asyn(' http://192。168 .1 .103:8080/ok http server/文件上传',//
新OkHttpClientManager .ResultCallbackString()
{
@覆盖
公共void onError(请求请求IOException e)
{
e。printstacktrace();
}
@覆盖
公共响应时无效(字符串结果)
{
}
},//
文件,//
' mFile ',//
新OkHttpClientManager .Param[]{
新OkHttpClientManager .Param('username ',' zhy '),
新OkHttpClientManager .Param('password ',' 123')}
);
键值对没什么说的,参数3为文件,参数四为文件对应的姓名,这个名字不是文件的名字;
对应于超文本传送协议(超文本传输协议的缩写)中的
输入类型='文件'名称='mFile '
对应的是名字后面的值,即mFile .
3.文件下载
对于文件下载,提供url,目标总监,回拨即可。
okhttpclientmanager。下载asyn(
' http://192 .168 .1 .103:8080/okhttp server/files/messenger _ 01。巴布亚新几内亚',
环境。getxternalstoragedirectory().getabsolutepath(),
新OkHttpClientManager .ResultCallbackString()
{
@覆盖
公共see on error(请求,IOException e)
{
}
@覆盖
公共响应无效(字符串响应)
{
//文件下载成功,这里回调的回答我为文件的绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对绝对
}
});
4.展示图片
展示图片,我们希望提供一个网址(URL)和一个imageview,如果下载成功,直接帮我们设置上即可。
okhttpclient管理器。显示图像(mimageview,
http://个图像。csdn。net/20150871/1。jpg
内部会自动根据图像视图-影像检视的大小自动对图片进行合适的压缩。虽然,这里可能不适合一次性加载大量图片的场景,但是对于应用程序(应用程序)中偶尔有几个图片的加载,还是可用的。
四、整合Json美元
很多人提出项目中使用时,服务端返回的是JSON!JSON!JSON!JSON字符串,希望客户端回调可以直接拿到对象,于是整合进入了json先生,完善该功能。
(一)直接回调对象
例如现在有个用户(用户)实体类:
包com。zhy。utils。http。okhttp:
公共类用户
公共字符串用户名;
公共字符串口令;
公共用户()
//所有自动生成的构造函数存根
}
公共用户(字符串用户名,字符串密码)>
此。用户名=用户名
this.password=密码:
}
@覆盖
公共字符串toString()
{
返回用户{ }
用户名=' '用户名' "
密码=' '密码' '
' } ';
}
}
服务端返回:
{ '用户名':' zh ','密码':' 123'}
客户端可以如下方式调用:
okhttpclient管理器。获取syn(' http://192。168 .56 .1:8080/okhttpserver/user!获取者,
新OkHttpClientManager .结果回调用户()
{
@覆盖
公共see on error(请求,异常e)
{
e。print stack trace();
}
@覆盖
公共响应无效(用户响应)
{
MTV。settext(u . tostring());//用户界面线程
}
});
我们传入泛型用户(用户),在回应时-回应里面直接回调用户(用户)对象。
这里特别要注意的事,如果在JSON!JSON!JSON!JSON字符串-实体对象过程中发生错误,程序不会崩溃,出错方法会被回调。
注意:这里做了少许的更新,接口命名从字符串回调修改为结果回调。接口中的不信任方法修改为错误函数。
(二)回调对象集合
依然是上述的用户(用户)类,服务端返回
[{ '用户名':' zh ','密码':' 123'},{ '用户名':' lmj ','密码':' 12345'}]
则客户端可以如下调用:
okhttpclient管理器。获取syn(' http://192。168 .56 .1:8080/okhttpserver/user!获取用户(获取者),
新OkHttpClientManager .结果回调ListUser()
{
@覆盖
公共see on error(请求,异常e)
{
e。print stack trace();
}
@覆盖
公共响应无效(列表用户美国)
{
Log.e('标签,美国。size()');
mTv.setText(美国获取(1)。tostring();
}
});
唯一的区别,就是泛型变为ListUser,好吧,如果发现错误(bug)或者有任何意见欢迎留言。
-
源码美元
好吧,基本介绍完了,对于封装的代码其实也很简单,我就直接贴出来了,因为也没什么好介绍的,如果你看完上面的用法,肯定可以看懂:
包com。zhy。utils。http。okhttp:
导入android.graphics.Bitmap:
导入android.graphics.BitmapFactory:
导入android.os处理程序:
导入安卓。os。尺蠖
导入安卓。小部件。图像视图
导入com。谷歌。gson。gson
导入com。谷歌。gson。内部。$ gson $ types
导入com.squareup.okhttp.Call:
导入com。干杯。好的http。回拨:
导入com。干杯。好的http。formcodeingbuilder
导入com.squareup.okhttp.Headers:
导入com.squareup.okhttp.MediaType:
导入com。干杯。好的http。多生成器;
导入com。干杯。好的http。好的http客户端:
导入com。干杯。好的http。请求:
导入com。干杯。好的http。请求正文:
导入com.squareup.okhttp.Response:
导入java.io.File:
导入Java . io . file输出流:
导入java。超正析象管异常:
导入java.io.InputStream:
导入Java。郎。反思。参数过程类型:
导入Java。郎。反思。类型;
导入Java。网。cookiemanager
导入Java。网。cookiepolicy
导入Java。网。文件名映射;
导入Java。网。URL连接;
导入Java。util。hashmap
导入Java。util。地图;
导入Java。util。设置;
/**
*由zhy于2017年8月15日创建。
*/
公共类OkHttpClientManager
{
私有静态OkHttpClientManager mInstance
private OkHttpClient mOkHttpClient;
私有处理程序mDelivery
列兵Gson mGson
private static final String TAG=' OkHttpClientManager ';
私有OkHttpClientManager()
{
mOkHttpClient=new OkHttpClient();
//cookie已启用
mokhttpclient。setcookiehandler(新的CookieManager(null,CookiePolicy .接受_原始_服务器));
mDelivery=新处理程序(looper。getmainlooper());
MGS on=新Gson();
}
公共静态OkHttpClientManager getInstance()
{
if (mInstance==null)
{
同步(OkHttpClientManager.class)
{
if (mInstance==null)
{
mInstance=new OkHttpClientManager();
}
}
}
回报;
}
/**
* 同步的得到请求
*
* @param url
* @返回响应
*/
私有响应_getAsyn(字符串网址)抛出IOException
{
最终请求请求=新请求。构建器()。网址(网址)。build();
Call call=mOkHttpClient.newCall(请求);
响应执行=调用。执行();
返回执行
}
/**
* 同步的得到请求
*
* @param url
* @返回字符串
*/
private String _getAsString(字符串网址)抛出IOException
{
response execute=_ geta syn(URL);
返回execute.body()。string();
}
/**
* 异步的得到请求
*
* @param url
* @param回调
*/
private void _getAsyn(字符串url,最终结果回调回调)
{
最终请求请求=新请求。构建器()。网址(网址)。build();
交付结果(回调,请求);
}
/**
* 同步的邮政请求
*
* @param url
* @param params帖子的参数
* @返回
*/
私有Response _post(字符串url,参数.参数)引发IOException
{
request request=buildPostRequest(URL,params);
response response=mokhttpclient。新呼叫(请求)。执行();
返回响应;
}
/**
* 同步的邮政请求
*
* @param url
* @param params帖子的参数
* @返回字符串
*/
private String _postAsString(字符串url,参数.参数)引发IOException
{
Response response=_post(url,params);
返回response.body().string();
}
/**
* 异步的邮政请求
*
* @param url
* @param回调
* @param params
*/
私有void _postAsyn(字符串url,最终结果回调回调,参数.参数)
{
request request=buildPostRequest(URL,params);
交付结果(回调,请求);
}
/**
* 异步的邮政请求
*
* @param url
* @param回调
* @param params
*/
私有void _postAsyn(字符串url,最终结果回调回调,映射字符串,字符串参数)
{
param[]params arr=map 2 params(params);
request request=buildPostRequest(URL,params arr);
交付结果(回调,请求);
}
/**
* 同步基于邮政的文件上传
*
* @param params
* @返回
*/
私人回应_帖子(字符串url,文件[]文件,字符串[]文件密钥,参数.参数)引发IOException
{
request request=buildMultipartFormRequest(URL,files,fileKeys,params);
返回mOkHttpClient.newCall(请求)。执行();
}
私人回应_帖子(字符串url,文件文件,字符串文件密钥)抛出IOException
{
request request=buildMultipartFormRequest(URL,新文件[]{文件},新字符串[]{fileKey},null);
返回mOkHttpClient.newCall(请求)。执行();
}
私人回应_帖子(字符串url,文件文件,字符串文件密钥,参数.参数)引发IOException
{
request request=buildMultipartFormRequest(URL,new File[]{file},new String[]{fileKey},params);
返回mOkHttpClient.newCall(请求)。执行();
}
/**
* 异步基于邮政的文件上传
*
* @param url
* @param回调
* @param文件
* @param fileKeys
* @抛出IOException
*/
私有void _postAsyn(字符串url,ResultCallback回调,File[] files,String[]filekey,Param.参数)引发IOException
{
request request=buildMultipartFormRequest(URL,files,fileKeys,params);
交付结果(回调,请求);
}
/**
* 异步基于邮政的文件上传,单文件不带参数上传
*
* @param url
* @param回调
* @param文件
* @param fileKey
* @抛出IOException
*/
私有void _postAsyn(字符串url,结果回调回调,文件文件,字符串文件密钥)抛出IOException
{
request request=buildMultipartFormRequest(URL,新文件[]{文件},新字符串[]{fileKey},null);
交付结果(回调,请求);
}
/**
* 异步基于邮政的文件上传,单文件且携带其他形式参数上传
*
* @param url
* @param回调
* @param文件
* @param fileKey
* @param params
* @抛出IOException
*/
私有void _postAsyn(字符串url,结果回调回调,文件文件,字符串文件密钥,参数.参数)引发IOException
{
request request=buildMultipartFormRequest(URL,new File[]{file},new String[]{fileKey},params);
交付结果(回调,请求);
}
/**
* 异步下载文件
*
* @param url
* @param destFileDir本地文件存储的文件夹
* @param回调
*/
私有void _downloadAsyn(最终字符串url,最终字符串destFileDir,最终结果回调回调)
{
最终请求请求=新请求。构建器()。网址(网址)。build();
最终呼叫Call=mokhttpclient。新呼叫(请求);
调用.入队(新回调()
{
@覆盖
失败时公共无效(最终请求请求,最终超正析象管异常e)
{
sendFailedStringCallback(请求,e,回调);
}
@覆盖
公共响应无效(响应响应)
{
输入流为=空
字节[]缓冲区=新字节[2048];
int len=0;
FileOutputStream fos=null
尝试
{
is=response.body().byteStream();
File file=new File(destFileDir,getFileName(URL));
fos=新文件输出流(文件);
while ((len=is.read(buf))!=-1)
{
fos.write(buf,0,len);
}
福斯。flush();
//如果下载文件成功,第一个参数为文件的绝对路径
sendcsuccessresultcallback(文件。getabsolutepath(),回调);
} catch (IOException e)
{
sendFailedStringCallback(响应。request(),e,回调);
}最后
{
尝试
{
如果(是!=空)是。close();
} catch (IOException e)
{
}
尝试
{
如果(fos!=null)fos。close();
} catch (IOException e)
{
}
}
}
});
}
私有字符串获取文件名(字符串路径)
{
整数分隔符索引=路径。lastindexof('/');
return (separatorIndex 0)?路径:路径。子字符串(分隔符索引1,路径。length());
}
/**
* 加载图片
*
* @param视图
* @param url
* @抛出IOException
*/
私有void _displayImage(最终图像视图视图,最终字符串url,最终int errorResId)
{
最终请求请求=新请求。构建器()。网址(网址)。build();
Call call=mOkHttpClient.newCall(请求);
调用.入队(新回调()
{
@覆盖
失败时的公共无效(请求请求IOException e)
{
setErrorResId(视图,错误resid);
}
@覆盖
公共响应无效(响应响应)
{
输入流为=空
尝试
{
is=response.body().byteStream();
图像工具.ImageSize actualImageSize=imageutils。getimagesize(is);
图像工具.ImageSize image viewsize=图像实用程序。getimageviewsize(视图);
int inSampleSize=imageutils。calculateinsamplesize(actualImageSize,imageViewSize);
尝试
{
是。reset();
} catch (IOException e)
{
response=_ geta syn(URL);
is=response.body().byteStream();
}
位图工厂Options ops=new BitmapFactory .options();
ops.inJustDecodeBounds=false
ops.inSampleSize=inSampleSize
最终位图BM=位图工厂。解码流(is,null,ops);
mDelivery.post(新的可运行()
{
@覆盖
公共无效运行()
{
查看。setimage位图(BM);
}
});
} catch(异常e)
{
setErrorResId(视图,错误resid);
}最后
{
如果(是!=空)尝试
{
是。close();
} catch (IOException e)
{
e。printstacktrace();
}
}
}
});
}
私有void setErrorResId(最终图像视图视图,最终int errorResId)
{
mDelivery.post(新的可运行()
{
@覆盖
公共无效运行()
{
查看。设置图像资源(错误resid);
}
});
}
//*************对外公布的方法************
公共静态响应getAsyn(字符串网址)引发IOException
{
返回getInstance()._ geta syn(URL);
}
公共静态字符串getAsString(字符串网址)引发IOException
{
返回getInstance()._ getAsString(URL);
}
公共静态void getAsyn(字符串url,结果回调回调)
{
getInstance()._getAsyn(url,回调);
}
公共静态响应帖子(字符串url,参数.参数)引发IOException
{
返回getInstance()._post(url,params);
}
公共静态字符串邮政字符串(字符串url,参数.参数)引发IOException
{
返回getInstance()._postAsString(url,params);
}
公共静态void postAsyn(字符串url,最终结果回调回调,参数.参数)
{
getInstance()._postAsyn(url,callback,params);
}
公共静态void postAsyn(字符串url,最终结果回调回调,映射字符串,字符串参数)
{
getInstance()._postAsyn(url,callback,params);
}
公共静态响应帖子(字符串url,文件[]文件,字符串[]文件密钥,参数.参数)引发IOException
{
返回getInstance()._张贴(url,文件、文件密钥、参数);
}
公共静态响应帖子(字符串url,文件文件,字符串文件密钥)引发IOException
{
返回getInstance()._post(url、文件、文件密钥);
}
公共静态响应帖子(字符串url,文件文件,字符串文件密钥,参数.参数)引发IOException
{
返回getInstance()._post(url,file,fileKey,params);
}
公共静态void post asyn(字符串URL,ResultCallback回调,File[] files,String[]filekey,Param.参数)引发IOException
{
getInstance()._postAsyn(url,回调、文件、文件密钥、参数);
}
公共静态void postAsyn(字符串url,结果回调回调,文件文件,字符串文件密钥)抛出IOException
{
getInstance()._postAsyn(url、回调、文件、文件密钥);
}
公共静态void postAsyn(字符串url,结果回调回调,文件文件,字符串文件密钥,参数.参数)引发IOException
{
getInstance()._postAsyn(url,callback,file,fileKey,params);
}
公共静态void显示图像(最终图像视图视图,字符串url,int errorResId)引发IOException
{
getInstance()._displayImage(视图、url、错误resid);
}
公共静态void显示图像(最终图像视图视图,字符串网址)
{
getInstance()._显示图像(视图,网址,-1);
}
公共静态void downloadAsyn(字符串url,字符串destDir,结果回调回调)
{
getInstance()._downloadAsyn(url,destDir,callback);
}
//****************************
私有请求buildMultipartFormRequest(字符串url,File[]文件,
String[] fileKeys,Param[] params)
{
params=validate param(参数);
多生成器生成器=新的多部件构建器()。类型(多生成器.形式);
对于(参数参数:参数参数)
{
建筑商。添加部分(标题。of('内容-配置','表单-数据;name='' param.key ' '),
RequestBody.create(null,param。值));
}
if (files != null) { RequestBody fileBody = null; for (int i = 0; i < files.length; i++) { File file = files[i]; String fileName = file.getName(); fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file); //TODO 根据文件名设置contentType builder.addPart(Headers.of("Content-Disposition", "form-data; name="" + fileKeys[i] + ""; filename="" + fileName + """), fileBody); } } RequestBody requestBody = builder.build(); return new Request.Builder() .url(url) .post(requestBody) .build(); } private String guessMimeType(String path) { FileNameMap fileNameMap = URLConnection.getFileNameMap(); String contentTypeFor = fileNameMap.getContentTypeFor(path); if (contentTypeFor == null) { contentTypeFor = "application/octet-stream"; } return contentTypeFor; } private Param[] validateParam(Param[] params) { if (params == null) return new Param[0]; else return params; } 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; } private static final String SESSION_KEY = "Set-Cookie"; private static final String mSessionKey = "JSESSIONID"; private Map<String, String> mSessions = new HashMap<String, String>(); private void deliveryResult(final ResultCallback callback, Request request) { mOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(final Request request, final IOException e) { sendFailedStringCallback(request, e, callback); } @Override public void onResponse(final Response response) { try { final String string = response.body().string(); if (callback.mType == String.class) { sendSuccessResultCallback(string, callback); } else { Object o = mGson.fromJson(string, callback.mType); sendSuccessResultCallback(o, callback); } } catch (IOException e) { sendFailedStringCallback(response.request(), e, callback); } catch (com.google.gson.JsonParseException e)//Json解析的错误 { sendFailedStringCallback(response.request(), e, callback); } } }); } private void sendFailedStringCallback(final Request request, final Exception e, final ResultCallback callback) { mDelivery.post(new Runnable() { @Override public void run() { if (callback != null) callback.onError(request, e); } }); } private void sendSuccessResultCallback(final Object object, final ResultCallback callback) { mDelivery.post(new Runnable() { @Override public void run() { if (callback != null) { callback.onResponse(object); } } }); } private Request buildPostRequest(String url, Param[] params) { if (params == null) { params = new Param[0]; } FormEncodingBuilder builder = new FormEncodingBuilder(); for (Param param : params) { builder.add(param.key, param.value); } RequestBody requestBody = builder.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]); } public abstract void onError(Request request, Exception e); public abstract void onResponse(T response); } public static class Param { public Param() { } public Param(String key, String value) { this.key = key; this.value = value; } String key; String value; } }源码地址:demo下载http://xiazai.jb51.net/201611/yuanma/okhttputils-master_jb51.zip 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。