OkHttp3初探:基本使用方法

目录

一、简介

二、基本用法

1、添加依赖

2、使用

2.1 创建客户端对象

2.2 创建Request对象

2.3 生成网络请求对象

2.4 发起网络请求

2.5 示例

三、补充知识

3.1 RequestBody

3.2 Response

四、主要参考


一、简介

OkHttp3是由square公司负责日常维护的开源项目,GitHub地址:https://github.com/square/okhttp ;

其中 3.14.x版本及以前的版本,均采用Java语言编写,4.0.0以后的采用kotlin语言编写;

本系列文章中源码均引用自3.14.x版本;

经过市场考验,公认为Android中最好用的网络开源框架,在日常开发中基本上完全取代了Google官方推荐的UrlConnection;

二、基本用法

1、添加依赖

implementation 'com.squareup.okhttp3:okhttp:3.14.0'
implementation 'com.squareup.okio:okio:1.15.0'

2、使用

2.1 创建客户端对象

OkHttpClient okHttpClient = new OkHttpClient(); // 创建OkHttpClient对象

2.2 创建Request对象

(1)默认采用GET请求

Request request = new Request.Builder()
                    .url("your.interface?param_one=\"\"¶m_two=\"\"") // 接口地址
                    .build(); // 创建Request对象

(2) 采用POST请求

/**
    先创建RequestBody,再调用Request的post方法
*/

/** 以FormBody为例 FormBody为RequestBody的子类 */

FormBody.Builder formBody = new FormBody.Builder(); // 创建FormBody
formBody.add("key","value"); // 传递键值对参数,即时组装
Request request = new Request.Builder() // 创建Request对象
            .url("your_interface")
            .post(formBody.build()) // 传递RequestBody对象
            .build();

2.3 生成网络请求对象

RealCall realCall = okHttpClient.newCall(request);

2.4 发起网络请求

(1)同步请求

/**
 * 须新开一个子线程执行RealCall.execute();
 * 以下为一个 (GET + 同步) 的网络请求示例 
 */
new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                OkHttpClient okHttpClient = new OkHttpClient(); 
                Request request = new Request.Builder()
                        .url("your_interface") 
                        .build();
                Response response = null;
                RealCall realCall = OkHttpClient.newCall(request);
                response = realCall.execute(); // 得到Response 对象
                if (response.isSuccessful()) {
                  // 拿到返回结果
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();

(2)异步请求

/** 
 * realCall直接执行enqueue方法
 * enqueue()自动在子线程中异步执行网络请求
 */
realCall.enqueue(new Callback{

    @Override
    public void onResponse(Call call, Response response) throws IOException{
        if(response.isSuccessful()){
            // 拿到返回结果,在子线程中执行 
        }
    }    
    
    @Override
    public void onFailure(Call call, IOException e){
        // 异常处理
    }
    
});

2.5 示例

/** POST + 异步 */

// 创建OkHttpClient对象
OkHttpClient okHttpClient = new OkHttpClient(); 

// 创建Request对象
FormBody.Builder formBody = new FormBody.Builder(); 
formBody.add("key","value"); 
Request request = new Request.Builder() 
            .url("your_interface")
            .post(formBody.build()) 
            .build();

// 发起异步网络请求
okHttpClient.newCall(request).enqueue(new Callback{

    @Override
    public void onResponse(Call call, Response response) throws IOException{
        if(response.isSuccessful()){
            // 拿到返回结果,在子线程中执行 
        }
    }    
    
    @Override
    public void onFailure(Call call, IOException e){
        // 异常处理
    }
    
});

三、补充知识

3.1 RequestBody

对于POST请求,须想post方法传参RequestBody实例,根据不同的需求,有以下几种常见的实现方式:

(1)FormBody

表单类实例,适合传输键值对参数:

FormBody.Builder formBody = new FormBody.Builder();
formBody.add("key","value");
RequestBody requestBody = formBody.build();

(2) JSON格式对象或者File对象

1)对于json格式数据

MediaType JSON = MediaType.parse("application/json; charset=utf-8"); 
String json = "{\"key_one\":\"value_one\",\"key_two\":\"value_two\"}"; 
RequestBody requestBody = RequestBody.create(josn, JSON);

2) 对于File类型数据

MediaType fileType = MediaType.parse("File/*"); 
File file = new File("your_file_path"); 
RequestBody requestBody = RequestBody.create(fileType , file);

3) MultipartBody

同时传递键值对参数与File类型参数

// 生成File类型的RequestBody
MediaType fileType = MediaType.parse("File/*"); 
File file = new File("your_file_path"); 
RequestBody requestBody = RequestBody.create(fileType , file);

// 生成MultipartBody
MultipartBody multipartBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("key_one", "value_one") 
        .addFormDataPart("key_two", "value_two")
        .addFormDataPart("file", file.getName(), requestBody)
        .build();

// 将MultipartBody传入post方法
Request request = new Request.Builder()
        .url(”your_interface“)
        .post(multipartBody)
        .build();

4)自定义RequestBody

// 将自定义的requestBody实例直接传入post方法
// 可以传输流
RequestBody requestBody = new RequestBody() {
    @Override
    public MediaType contentType() {
        return null;
    }
 
    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        // 重写writeTo方法
        FileInputStream fileInputStream = new FileInputStream(new File("file_name"));
        byte[] buffer = new byte[1024*8];
        if(fileInputStream.read(buffer) != -1){
             sink.write(buffer);
        }
    }
};

3.2 Response

注意事项:

1、Response.code是http响应行中的code,如果访问成功则返回200.这个不是服务器设置的,而是http协议中自带的。res中的code才是服务器设置的。注意二者的区别。

2、response.body().string()本质是输入流的读操作,所以它还是网络请求的一部分,所以这行代码必须放在子线程

3、response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。原因是:response.body().string()的本质是输入流的读操作,必须有服务器的输出流的写操作时客户端的读操作才能得到数据。而服务器的写操作只执行一次,所以客户端的读操作也只能执行一次,第二次将返回null。

 

四、主要参考

参考链接(1):https://github.com/square/okhttp

参考链接(2):https://blog.csdn.net/qq_17470165/article/details/80543537

参考链接(3):https://blog.csdn.net/suyimin2010/article/details/80196443

 

 

 

你可能感兴趣的:(Android)