OkHttp是Square公司的出品,一个Http请求库,Google官方文档不推荐人们使用HttpClient,可是HttpURLConnection 实在是太难用了,因此很多人使用了OkHttp 来解决这问题, Android4.4 的源码中HttpURLConnection 已经替换成OkHttp 实现。
使用OkHttp的好处
1、OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。
2、使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。如果你用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。
在APP中build.gradle配置依赖包,okHttp依赖okIo所以需要导入okIo包
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okio:okio:1.10.0'
2、基本使用
/**
* Http Get 请求
*/
private void httpGet() {
///创建okHttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//创建一个Request Request是OkHttp中访问的请求,Builder是辅助类。Response即OkHttp中的响应。
final Request request = new Request.Builder()
.url("http://ip.taobao.com/service/getIpInfo.php?ip=63.223.108.42")
.build();
//得到一个call对象
Call call = mOkHttpClient.newCall(request);
//请求加入调度
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败
Log.e("TAG", "请求失败");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//不是UI线程,请不要在此更新界面
String htmlStr = response.body().string();
Log.e("TAG", "htmlStr ==" + htmlStr);
}
});
}
以上就是发送一个get请求的步骤,首先构造一个Request对象,参数最起码有个url,当然你可以通过Request.Builder设置更多的参数比如:
header
、method
等。
然后通过request的对象去构造得到一个Call对象,类似于将你的请求封装成了任务,既然是任务,就会有
execute()
和cancel()
等方法。
最后,以异步的方式去执行请求,所以我们调用的是call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。
3、Http中POST请求
/**
* Http Post请求
*/
private void httpPost() {
OkHttpClient mOkHttpClient = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
.add("ip", "63.223.108.42")
.build();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("http://ip.taobao.com/service/getIpInfo.php?")
.post(requestBody)
.build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败
Log.e("TAG", "请求失败");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String htmlStr = response.body().string();
Log.e("TAG", "htmlStr ==" + htmlStr);
}
});
}
使用Request的post方法来提交请求体RequestBody
RequestBody类为绑定请求参数如果有多个参数绑定方法如下:
RequestBody requestBody = new FormBody.Builder()
.add("ip", "63.223.108.42")
.add("ip1", "63.223.108.43")
.add("ip2", "63.223.108.44")
.build();
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
属性:
text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
以application开头的媒体格式类型:
application/xhtml+xml :XHTML格式
application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式
application/json : JSON数据格式
application/pdf :pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded :
将
sdcard
根目录的test.txt文件上传到服务器
/**
* 上传文件
*/
private void postAsynFile() {
OkHttpClient mOkHttpClient = new OkHttpClient();
File file = new File("/sdcard/test.txt");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("TAG", "上传失败!");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e("TAG", response.body().string());
}
});
}
注:测试时在test.txt文件中是什么文字,服务器将会把里面的文字返回表示成功。
/**
* 下载文件
*/
private void downAsynFile() {
OkHttpClient mOkHttpClient = new OkHttpClient();
String url = "https://www.baidu.com/img/bd_logo1.png";
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/baidu.png"));
byte[] buffer = new byte[2048];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.flush();
} catch (IOException e) {
Log.e("TAG", "IOException");
e.printStackTrace();
}
Log.d("TAG", "文件下载成功");
}
});
}
根据上面代码写多个请求肯定包含大量的重复代码,所以需要进行封装,在GitHub上有个封装非常好的工具类名为OkHttpUtils,地址:https://github.com/hongyangAndroid/okhttputils
OkHttpClientManager.getAsyn("https://www.baidu.com", new OkHttpClientManager.ResultCallback()
{
@Override
public void onError(Request request, Exception e)
{
e.printStackTrace();
}
@Override
public void onResponse(String u)
{
mTv.setText(u);//注意这里是UI线程
}
});
对于一般的请求,我们希望给个url,然后CallBack里面直接操作控件。
2、OkHttpUtils文件上传且携带参数
OkHttpClientManager.postAsyn("http://192.168.1.103:8080/okHttpServer/fileUpload",//
new OkHttpClientManager.ResultCallback()
{
@Override
public void onError(Request request, IOException e)
{
e.printStackTrace();
}
@Override
public void onResponse(String result)
{
}
},//
file,//第三个参数 文件
"mFile",//文件名 对应于http中的
new OkHttpClientManager.Param[]{
new OkHttpClientManager.Param("username", "zhy"),
new OkHttpClientManager.Param("password", "123")}
);
OkHttpClientManager.downloadAsyn(
"http://192.168.1.103:8080/okHttpServer/files/messenger_01.png",
Environment.getExternalStorageDirectory().getAbsolutePath(),
new OkHttpClientManager.ResultCallback()
{
@Override
public void onError(Request request, IOException e)
{
}
@Override
public void onResponse(String response)
{
//文件下载成功,这里回调的reponse为文件的absolutePath
}
});
在Github上有有个封装好的okhttputils类,使用起来非常方便
https://github.com/hongyangAndroid/okhttputils
该封装类是鸿洋大神编写,博客地址
http://blog.csdn.net/lmj623565791/article/details/47911083