今天,简单讲讲Android里如何使用OKHttp。

 

Android框架系列:

一.android EventBus的简单使用

二.android Glide简单使用

三.android OKHttp的基本使用详解

 

简单说一下学习okhttp的理由

  1. google在Android 6.0中删除了HttpClient的Api,采用的是则是okhttp
  2. 高效的使用HTTP,使应用运行更快更省流量
  3. 响应缓存数据避免重复网络请求
  4. 无缝的支持GZIP来减少数据流量
  5. 使用非常简单,请求和响应的Api具有流畅的建造和不变性,同时支持同步异步调用回调函数
  6. 如果网络出现问题,它会从常见的连接问题中恢复
  7. 如果服务器配置有多个IP地址,当第一个IP连接失败,它会尝试连接下一个IP

一,OKHttp介绍

okhttp是一个第三方类库,用于android中请求网络。

这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient(android API23 里已移除HttpClient)。

okhttp有自己的官网,官网网址:OKHttp官网

如果想了解原码可以在github上下载,地址是:https://github.com/square/okhttp

在AndroidStudio中使用不需要下载jar包,直接添加依赖即可:
compile ‘com.squareup.okhttp3:okhttp:3.4.1’

下面对以OKHttp3来详细介绍OKHttp的使用方法。

二,get请求的使用方法

使用OKHttp进行网络请求支持两种方式,一种是同步请求,一种是异步请求。下面分情况进行介绍。

1,get的同步请求

对于同步请求在请求时需要开启子线程,请求成功后需要跳转到UI线程修改UI。

在AndroidManifest.xml添加所需权限


使用示例如下:

public void getDatasync(){    new Thread(new Runnable() {        @Override        public void run() {            try {                OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象                Request request = new Request.Builder()                        .url("http://www.baidu.com")//请求接口。如果需要传参拼接到接口后面。                        .build();//创建Request 对象                Response response = null;                response = client.newCall(request).execute();//得到Response 对象                if (response.isSuccessful()) {                Log.d("kwwl","response.code()=="+response.code());                Log.d("kwwl","response.message()=="+response.message());                Log.d("kwwl","res=="+response.body().string());                //此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。                }            } catch (Exception e) {                e.printStackTrace();            }        }    }).start();}

此时打印结果如下:
response.code()==200;
response.message()==OK;
res=={“code”:200,”message”:success};

注意事项:
1,Response.code是http响应行中的code,如果访问成功则返回200.这个不是服务器设置的,而是http协议中自带的。res中的code才是服务器设置的。注意二者的区别。
2,response.body().string()本质是输入流的读操作,所以它还是网络请求的一部分,所以这行代码必须放在子线程。
3,response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。原因是:response.body().string()的本质是输入流的读操作,必须有服务器的输出流的写操作时客户端的读操作才能得到数据。而服务器的写操作只执行一次,所以客户端的读操作也只能执行一次,第二次将返回null。

 

2,get的异步请求

这种方式不用再次开启子线程,但回调方法是执行在子线程中,所以在更新UI时还要跳转到UI线程中。
使用示例如下:

private void getDataAsync() {    OkHttpClient client = new OkHttpClient();    Request request = new Request.Builder()            .url("http://www.baidu.com")            .build();    client.newCall(request).enqueue(new Callback() {        @Override        public void onFailure(Call call, IOException e) {        }        @Override        public void onResponse(Call call, Response response) throws IOException {            if(response.isSuccessful()){//回调的方法执行在子线程。                Log.d("kwwl","获取数据成功了");                Log.d("kwwl","response.code()=="+response.code());                Log.d("kwwl","response.body().string()=="+response.body().string());            }        }    });}

异步请求的打印结果与注意事项与同步请求时相同。最大的不同点就是异步请求不需要开启子线程,enqueue方法会自动将网络请求部分放入子线程中执行。

注意事项:
1,回调接口的onFailure方法和onResponse执行在子线程。
2,response.body().string()方法也必须放在子线程中。当执行这行代码得到结果后,再跳转到UI线程修改UI。

 

三,post请求的使用方法

Post请求也分同步和异步两种方式,同步与异步的区别和get方法类似,所以此时只讲解post异步请求的使用方法。
使用示例如下:

private void postDataWithParame() {    OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。    FormBody.Builder formBody = new FormBody.Builder();//创建表单请求体    formBody.add("username","zhangsan");//传递键值对参数    Request request = new Request.Builder()//创建Request 对象。            .url("http://www.baidu.com")            .post(formBody.build())//传递请求体            .build();    client.newCall(request).enqueue(new Callback() {。。。});//回调方法的使用与get异步请求相同,此时略。}

看完代码我们会发现:post请求中并没有设置请求方式为POST,回忆在get请求中也没有设置请求方式为GET,那么是怎么区分请求方式的呢?重点是Request.Builder类的post方法,在Request.Builder对象创建最初默认是get请求,所以在get请求中不需要设置请求方式,当调用post方法时把请求方式修改为POST。所以此时为POST请求。

 

四,POST请求传递参数的方法总结

在post请求使用方法中讲了一种传递参数的方法,就是创建表单请求体对象,然后把表单请求体对象作为post方法的参数。post请求传递参数的方法还有很多种,但都是通过post方法传递的。下面我们看一下Request.Builder类的post方法的声明:

public Builder post(RequestBody body)

由方法的声明可以看出,post方法接收的参数是RequestBody 对象,所以只要是RequestBody 类以及子类对象都可以当作参数进行传递。FormBody就是RequestBody 的一个子类对象。

1,使用FormBody传递键值对参数

这种方式用来上传String类型的键值对
使用示例如下:

private void postDataWithParame() {    OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。    FormBody.Builder formBody = new FormBody.Builder();//创建表单请求体    formBody.add("username","zhangsan");//传递键值对参数    Request request = new Request.Builder()//创建Request 对象。            .url("http://www.baidu.com")            .post(formBody.build())//传递请求体            .build();    client.newCall(request).enqueue(new Callback() {。。。});//此处省略回调方法。}

2,使用RequestBody传递Json或File对象

RequestBody是抽象类,故不能直接使用,但是他有静态方法create,使用这个方法可以得到RequestBody对象。

这种方式可以上传Json对象或File对象。
上传json对象使用示例如下:

OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式,String jsonStr = "{\"username\":\"lisi\",\"nickname\":\"李四\"}";//json数据.RequestBody body = RequestBody.create(JSON, josnStr);Request request = new Request.Builder()        .url("http://www.baidu.com")        .post(body)        .build();client.newCall(request).enqueue(new Callback() {。。。});//此处省略回调方法。

上传File对象使用示例如下:

OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。MediaType fileType = MediaType.parse("File/*");//数据类型为json格式,File file = new File("path");//file对象.RequestBody body = RequestBody.create(fileType , file );Request request = new Request.Builder()        .url("http://www.baidu.com")        .post(body)        .build();client.newCall(request).enqueue(new Callback() {。。。});//此处省略回调方法。

3,使用MultipartBody同时传递键值对参数和File对象

这个字面意思是多重的body。我们知道FromBody传递的是字符串型的键值对,RequestBody传递的是多媒体,那么如果我们想二者都传递怎么办?此时就需要使用MultipartBody类。
使用示例如下:

OkHttpClient client = new OkHttpClient();MultipartBody multipartBody =new MultipartBody.Builder()        .setType(MultipartBody.FORM)        .addFormDataPart("groupId",""+groupId)//添加键值对参数        .addFormDataPart("title","title")        .addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("file/*"), file))//添加文件        .build();final Request request = new Request.Builder()        .url(URLContant.CHAT_ROOM_SUBJECT_IMAGE)        .post(multipartBody)        .build();client.newCall(request).enqueue(new Callback() {。。。});

4,自定义RequestBody实现流的上传

在上面的分析中我们知道,只要是RequestBody类以及子类都可以作为post方法的参数,下面我们就自定义一个类,继承RequestBody,实现流的上传。
使用示例如下:
首先创建一个RequestBody类的子类对象:

RequestBody body = new RequestBody() {    @Override    public MediaType contentType() {        return null;    }    @Override    public void writeTo(BufferedSink sink) throws IOException {//重写writeTo方法        FileInputStream fio= new FileInputStream(new File("fileName"));        byte[] buffer = new byte[1024*8];        if(fio.read(buffer) != -1){             sink.write(buffer);        }    }};

然后使用body对象:

 OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。Request request = new Request.Builder()        .url("http://www.baidu.com")        .post(body)        .build();client.newCall(request).enqueue(new Callback() {。。。});

以上代码的与众不同就是body对象,这个body对象重写了write方法,里面有个sink对象。这个是OKio包中的输出流,有write方法。使用这个方法我们可以实现上传流的功能。

使用RequestBody上传文件时,并没有实现断点续传的功能。我可以使用这种方法结合RandomAccessFile类实现断点续传的功能。

 

五,设置请求头

OKHttp中设置请求头特别简单,在创建request对象时调用一个方法即可。
使用示例如下:

Request request = new Request.Builder()                .url("http://www.baidu.com")                .header("User-Agent", "OkHttp Headers.java")                .addHeader("token", "myToken")                .build();

其他部分代码略。

六,下载文件

在OKHttp中并没有提供下载文件的功能,但是在Response中可以获取流对象,有了流对象我们就可以自己实现文件的下载。代码如下:
这段代码写在回调接口CallBack的onResponse方法中:

try{    InputStream  is = response.body().byteStream();//从服务器得到输入流对象    long sum = 0;    File dir = new File(mDestFileDir);    if (!dir.exists()){        dir.mkdirs();    }    File file = new File(dir, mdestFileName);//根据目录和文件名得到file对象    FileOutputStream  fos = new FileOutputStream(file);    byte[] buf = new byte[1024*8];    int len = 0;    while ((len = is.read(buf)) != -1){        fos.write(buf, 0, len);    }    fos.flush();    return file;}

 

超时设置,整个程序应使用这一个mOkHttpClient对象

    public static void setTimeout() {        mOkHttpClient.newBuilder().                connectTimeout(10, TimeUnit.SECONDS)//10秒连接超时         .writeTimeout(10, TimeUnit.SECONDS)//10m秒写入超时         .readTimeout(10, TimeUnit.SECONDS)//10秒读取超时         .build();     }

简单回顾一下,okhttp可以使用

private void getDataAsync() {    OkHttpClient client = new OkHttpClient();    Request request = new Request.Builder()            .url("http://www.baidu.com")            .build();    client.newCall(request).enqueue(new Callback() {        @Override        public void onFailure(Call call, IOException e) {        }        @Override        public void onResponse(Call call, Response response) throws IOException {            if(response.isSuccessful()){//回调的方法执行在子线程。                Log.d("kwwl","获取数据成功了");                Log.d("kwwl","response.code()=="+response.code());                Log.d("kwwl","response.body().string()=="+response.body().string());            }        }    });}

发生请求,同时指出Get和POST两种请求方式,结果在Callback里回调回来,记住是子线程,所以不能再回调修改UI.还有文件上传和下载也比较简单,具体的代码大家自己去看。

 

这里提供我学习时写的OKHttp的Demo:源码下载

 

android OKHttp的基本使用详解就讲完了。

 

就这么简单。

更多相关文章

  1. 【Android(安卓)Dev Guide - 03】 - Content Providers
  2. Android(安卓)TextView使用HTML处理字体样式、显示图片等
  3. Android线程间通信机制——深入理解 Looper、Handler、Message
  4. Intent的匹配与查找
  5. android中做网络请求的几种方式
  6. android 登陆、提交数据或加载数据时提示页面
  7. 浅谈Java中Collections.sort对List排序的两种方法
  8. 类和 Json对象
  9. Python list sort方法的具体使用

随机推荐

  1. WindowManager实现悬浮窗口
  2. 第四章 Android开发三大基石—Activity、
  3. Android中的观察者模式简单使用
  4. Android(安卓)Selector用法小记
  5. Android——使用ContentProvider在应用间
  6. Android的Drawable和Bitmap之间相关转换
  7. Android中的多线程机制
  8. React Native -1环境搭建(macOS--Android)
  9. Android之Menu选项菜单
  10. android 3D系列之光效篇