您的位置:首页 > 理论基础 > 计算机网络

okhttp 使用完全解析

2016-06-09 17:48 477 查看

前言

一直以来,我们都在寻找更好用的网络框架,很多大牛们也一直致力于网络框架的设计.只为了一个目标:简单易学,但是功能却强大,性能也不错.okhttp正是这样子的一个框架,越来越多的人使用它作为网络请求的框架,它的出现也将近一年了,那么现在就让我们来学习学习吧,就基于最新的版本进行讲解

本篇博客使用okhttp的同步方法来讲解,自己开启子线程,okhttp里面也有异步的处理,和以前的异步处理框架的使用时非常类似的,没有返回值,需要传入一个接口,作为回调,方法是void enqueue(Callback responseCallback);

环境要求

支持Android 2.3及其以上版本,要求Java JDK1.7以上

简单的一个get请求

首先添加依赖:compile 'com.squareup.okhttp3:okhttp:3.3.1'

xml布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.cxj.demotest.MainActivity">

<Button
android:layout_width="match_parent"
android:text="点我"
android:onClick="clickView"
android:layout_height="wrap_content" />
</RelativeLayout>
就是一个按钮

Activity中代码

public class MainActivity extends AppCompatActivity implements Runnable {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void clickView(View view) {

new Thread(this).start();
}

@Override
public void run() {
try {
//请求的网址
String url = "https://publicobject.com/helloworld.txt";

//创建网络请求框架
OkHttpClient client = new OkHttpClient();

//创建请求对象
Request request = new Request.Builder()
.url(url)
.build();

//执行请求返回结果
Response response = client.newCall(request).execute();

//打印返回的结果,以字符串的形式
System.out.println("result = " + response.body().string());

} catch (Exception e) {
System.out.println("请求失败" + e.getMessage() + "," + e.getCause());
}

}
}

运行效果



可以看到我们请求是成功的,请求的内容被打印在控制台上,而我从使用上面可以看出来,okhttp框架并不是一个异步的请求框架,如果你直接在主线程中请求,程序会挂掉

post请求之提交普通数据

post请求我们知道可以做get请求的事情,也可以做get请求做不到的提交文件,这里先演示提交普通数据
由于post请求没有可以测试的接口,所以这里博主自己弄了一个测试接口,使用springMvc快速搭建的一个测试项目,项目名称为Test
@RequestMapping("test")
@Controller
public class TestController {

/**
* 响应post请求
*
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value = "testPost")
public void testPost(HttpServletRequest request, HttpServletResponse response, //
String name, String pass) throws IOException {
System.out.println("name = " + name);
System.out.println("pass = " + pass);
response.getWriter().println("hello");
}

}

这里可以响应一个请求,请求地址是:http://localhost:8080/Test/test/testPost

这里不懂的童鞋可以不必过多深究,这里只是告诉大家这里有一个测试接口,请求可以接受两个参数name和pass
那我们就开始测试post请求吧
由于博主是开模拟器测试post请求,所以这里的localhost要跟换成对应的ip才可行,你们自己测试的时候也是,一定要记得更换localhost为对应的ip地址

那我们run方法中的代码就有所改变了
@Override
public void run() {
try {
//请求的网址
String url = "http://192.168.1.103:8080/Test/test/testPost";
//192.168.1.103是我电脑的ip,如果你看到这段代码,那么这个ip请你自己更换成你自己的

//创建网络请求框架
OkHttpClient client = new OkHttpClient();

FormBody.Builder builder = new FormBody.Builder();
builder.add("name","小金子");
builder.add("pass","123");

//构建了一个请求体
FormBody formBody = builder.build();

//创建请求对象
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();

//执行请求返回结果
Response response = client.newCall(request).execute();

//打印返回的结果,以字符串的形式
System.out.println("result = " + response.body().string());

} catch (Exception e) {
System.out.println("请求失败" + e.getMessage() + "," + e.getCause());
}

}


可以看到我们更改的代码无非就是多了一个请求体,我们接触web的童鞋都应该知道,post请求的数据是放在请求体中的,所以这里需要构建一个请求体对象,而普通字段的请求体,通过FormBody.Builder构建即可

请求提交后的效果,这里在服务器上看提交上来的数据



这里可以很清楚的看到两个参数被提交上来,所以普通数据的表单可以利用FormEncodingBuilder就可以完成需求啦

post请求提交json格式的数据

这个问题总结一下其实就是两点:

1.提交的数据不是键值对的形式,而是一个json格式

2.提交的请求标识请求的类型,这个是需要我们自己去实现的

而对于一个请求来说,json格式的请求无非就是提交一个字符串,构建一个RequestBodt,所以可以这样子做
public class JsonRequestParameter {

private JSONObject jb = new JSONObject();

private static JsonRequestParameter jsonRequestParameter = null;

/**
* 构造函数私有化
*/
private JsonRequestParameter() {
}

/**
* 获取单利的对象
*
* @return
*/
public static JsonRequestParameter getInstance() {
if (jsonRequestParameter == null) {
jsonRequestParameter = new JsonRequestParameter();
}
return jsonRequestParameter;
}

/**
* 添加参数
*
* @param key
* @param value
*/
public JsonRequestParameter addParameter(String key, String value) {
try {
jb.put(key, value);
} catch (Exception e) {
}
return this;
}

public JsonRequestParameter addParameter(String key, int value) {
try {
jb.put(key, value);
} catch (Exception e) {
}
return this;
}

public JsonRequestParameter addParameter(String key, String[] values) {
try {
JSONArray ja = new JSONArray();
for (int i = 0; values != null && i < values.length; i++) {
if (values[i] != null) {
ja.put(values[i]);
}
}
jb.put(key, ja);
} catch (Exception e) {
}
return this;
}

/**
* 构建出json字符串
*
* @return
*/
public RequestBody build() {
String s = jb.toString();
System.out.println("json请求体:" + s);
jb = new JSONObject();
RequestBody requestBody = RequestBody.create(Constant.mediaType, s);
return requestBody;
}

}
/**
* 请求的时候的类型
*/
public static final MediaType mediaType = MediaType.parse("application/json; charset=utf-8");


通过这段代码就可以构建一个json格式的RequestBody,然后就可以像FormBody一样使用啦!
RequestBody body = JsonRequestParameter.getInstance()
.addParameter("name", "小金子")
.addParameter("pass", 123)
.build();

//创建请求对象
Request request = new Request.Builder()
.url("http://......")
.post(body)
.build();

//执行请求返回结果
Response response = client.newCall(request).execute()
上面就是一个使用的范例

post请求之文件上传

文件上传这个功能其实真是无处不在,无论在手机端还是网页端,或多或少都会接触到文件上传的功能,这里主要对利用okhttp进行文件上传对一个详细的讲解
首先你得确定你的测试机有一个可用的文件可供你上传,有些模拟器SD卡不可用的,所以请先检查你有一个可用的测试文件然后再往下看

由于需要测试文件的上传,那么服务器添加一个测试post文件的代码
@RequestMapping("test")
@Controller
public class TestController {

/**
* 响应post请求
*
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value = "testPost")
public String testPost(HttpServletRequest request, HttpServletResponse response, //
String name, String pass) throws IOException {
System.out.println("name = " + name);
System.out.println("pass = " + pass);
return "success";
}

@RequestMapping(value = "uploadFile")
public String testPost(@RequestParam("file") MultipartFile file, String name, String pass) {

System.out.println("file-name = " + file.getOriginalFilename());
System.out.println("file-length = " + file.getSize());

System.out.println("name = " + name);
System.out.println("pass = " + pass);

return "success";
}

}


可以看到testPost就是我们响应上传文件的方法

Activity中的代码如下
@Override
public void run() {
try {
//请求的网址
String url = "http://192.168.1.103:8080/Test/test/uploadFile";
//192.168.1.103是我电脑的ip,如果你看到这段代码,那么这个ip请你自己更换成你自己的

//需要上传的文件
File f = new File(Environment.getExternalStorageDirectory(), "address.db");

//创建网络请求框架
OkHttpClient client = new OkHttpClient();

//创建文件部分的请求体对象
RequestBody fileRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), f);

//创建总的请求体对象,包含普通键值对和文件数据
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
//普通字段的部分
.addFormDataPart("name","小金子")
.addFormDataPart("pass","123")
//添加文件部分
.addFormDataPart("file",f.getName(),fileRequestBody)
.build();

//创建请求对象
Request request = new Request.Builder()
.addHeader("Connection","keep-alive")
.url(url)
.post(requestBody)
.build();

//执行请求返回结果
Response response = client.newCall(request).execute();

//打印返回的结果,以字符串的形式
System.out.println("result = " + response.body().string());

} catch (Exception e) {
System.out.println("请求失败" + e.getMessage() + "," + e.getCause());
}

}

在上述代码中,涉及到文件的类型,这个文件的类型可以到网站上通过文件的后缀名搜索得到,或者在Tomcat的conf目录中的web.xml文件中可以找到,如果没找到,就使用"application/octet-stream"即可
那么最后的效果呢





文件成功的被上传上去啦

多文件上传

对于多文件上传相信不用我多说了,就是多次调用addFormDataPart方法添加文件即可

这里把服务器tomcat运行的项目打包一下,给不会写服务器接口的朋友们使用
如果tomcat不会使用的亲们,可以自己查阅一下资料,运行一个已有的项目还是很简单的
把我分享的Test.zip解压缩放到webapps里面,然后启动tomcat就可以了

http://download.csdn.net/detail/u011692041/9545286

下面是备用的
https://yunpan.cn/cRVbmFDMZNWn8

访问密码 5d16

总结

从上述okhttp的使用来看,我们发现okhttp对请求封装是非的到位,3.0相比2.0,一些细节的调整更是让这个框架人性化
我从它的一些对象看的出来,面向对象编程这里有着很好的体现,让我用过了就觉得它适合我,我也喜欢用它
当然了,从使用上能看出来,还是有些繁琐的,所以这就需要使用的你去适度的封装,让它变得更简单
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: