前言
一直以来,我们都在寻找更好用的网络框架,很多大牛们也一直致力于网络框架的设计.只为了一个目标:简单易学,但是功能却强大,性能也不错.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就可以了
下面是备用的
访问密码 5d16
总结
从上述okhttp的使用来看,我们发现okhttp对请求封装是非的到位,3.0相比2.0,一些细节的调整更是让这个框架人性化
我从它的一些对象看的出来,面向对象编程这里有着很好的体现,让我用过了就觉得它适合我,我也喜欢用它
当然了,从使用上能看出来,还是有些繁琐的,所以这就需要使用的你去适度的封装,让它变得更简单