okhttp 使用完全解析

前言

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

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值