25、AndroidOkHttp

OkHttp

OkHttp是一个优秀的网络请求框架,在使用需要添加相应的依赖:

implementation "com.squareup.okhttp3:okhttp:3.11.0"

还有请求网络的权限:

GET请求

使用OkHttp进行Get请求只需要四步即可完成。

// 构建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
// 构造Request对象
Request request = new Request.Builder()
      .url("www.baidu.com")
      .get()
      .build();
//将Request封装为Call
Call call = client.newCall(request);

最后,根据需要调用同步或者异步请求方法即可

同步调用

//同步调用,返回Response,会抛出IO异常
Response response = call.execute();

异步调用

//异步调用,并设置回调函数
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Toast.makeText(OkHttpActivity.this, "get failed", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onResponse(Call call, final Response response) throws IOException {
        final String res = response.body().string();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                contentTv.setText(res);
            }
        });
    }
});

在使用OkHttp需要注意:

同步调用会阻塞主线程,一般不适用
异步调用的回调函数是在子线程,需要借助于 runOnUiThread() 方法或者Handler来处理。

POST提交键值对

使用OkHttp进行Post请求和进行Get请求很类似,只需要五步即可完成。

// 构建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
// 构建FormBody传入参数
FormBody formBody = new FormBody.Builder()
    .add("username", "admin")
    .add("password", "admin")
    .build();
// 构造Request对象,将FormBody作为Post方法的参数传入
Request request = new Request.Builder()
    .url("https:www.baidu.com")
    .post(formBody)
    .build();
//将Request封装为Call
Call call = client.newCall(request);

最后,调用请求,重写回调方法:

call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Toast.makeText(OkHttpActivity.this, "Post Failed", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        final String res = response.body().string();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                contentTv.setText(res);
            }
        });
    }
});

POST提交字符串

POST提交字符串就需要使用RequestBody,其中FormBody是RequestBody的子类。

// 构建OkHttpClient对象
OkHttpClient client = new OkHttpClient();
// 构建FormBody传入参数
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), "1111111111111111");
// 构造Request对象,将FormBody作为Post方法的参数传入
Request request = new Request.Builder()
        .url("www.baidu.com")
        .post(requestBody)
        .build();
//将Request封装为Call
Call call = client.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
    }
});

上面的MediaType我们指定传输的是纯文本,而且编码方式是utf-8,通过上面的方式我们就可以向服务端发送json字符串。

POST上传文件

这里我们以上传一张图片为例,演示OkHttp上传单文件:

OkHttpClient okHttpClient = new OkHttpClient();
File file = new File(Environment.getExternalStorageDirectory(), "1.png");
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"),file);
Request request = new Request.Builder()
        .url("www.baidu.com")
        .post(requestBody)
        .build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
    }
});

如果是多文件上传,可以使用表单的方式来提交:

List<String> fileNames = new ArrayList<>();
fileNames.add(Environment.getExternalStorageState() + "/1.png");
fileNames.add(Environment.getExternalStorageState() + "/2.png");
OkHttpClient okHttpClient = new OkHttpClient();
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
for (String fileName : fileNames) {
    File file = new File(fileName);
    builder.addFormDataPart("files", file.getName(), RequestBody.create(
            MediaType.parse("multipart/form-data"), file));
}
MultipartBody multipartBody = builder.build();
Request request = new Request.Builder()
        .url("www.baidu.com")
        .post(multipartBody)
        .build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
    }
});

POST提交表单

其中,MultipartBody是RequestBody的子类,提交表单需要使用它来构建RequestBody。

File file = new File(Environment.getExternalStorageDirectory(), "1.png");
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("username", "admin")
        .addFormDataPart("password", "admin")
        .addFormDataPart("file", file.getName(),
                RequestBody.create(MediaType.parse("application/octet-stream"), file))
        .build();
Request request = new Request.Builder()
        .url("www.baidu.com")
        .post(requestBody)
        .build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
    }
});

GET下载文件

下面将演示OkHttp使用GET请求下载文件的实例:

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
        .url("www.baidu.com/1.png")
        .get()
        .build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        InputStream inputStream = response.body().byteStream();
        int len;
        File file  = new File(Environment.getExternalStorageDirectory(), "1.png");
        FileOutputStream fos = new FileOutputStream(file);
        byte[] buf = new byte[128];

        while ((len = inputStream.read(buf)) != -1){
            fos.write(buf, 0, len);
        }
        fos.flush();
        fos.close();
        inputStream.close();
    }
});

可以通过流的读取来实现文件的上传和下载进度显示。

OkHttp拦截器

OkHttp的拦截器有五种内置的,除此之外还可以自定义拦截器。

  • retryAndFollowUpInterceptor:重试和重定向拦截器,主要负责网络失败重连。
  • BridgeInterceptor:主要负责添加交易请求头。
  • CacheInterceptor:缓存拦截器,主要负责拦截缓存。
  • ConnectInterceptor:网络连接拦截器,主要负责正式开启http请求。
  • CallServerInterceptor:负责发送网络请求和读取网络响应

这里主要介绍使用自定义日志拦截器来打印Logger信息。

1)创建HttpLogger类实现HttpLoggingInterceptor.Logger

public class HttpLogger implements HttpLoggingInterceptor.Logger {
    @Override
    public void log(String message) {
        Log.e("HttpLogInfo", message);
    }
}

2) 使用OkHttpClient.Builder添加拦截器

// Add Logger Interceptor
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLogger());
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
clientBuilder.addNetworkInterceptor(loggingInterceptor);

这样,就可以在请求网络的时候看到OkHttp的日志信息。

关于OkHttp还有很多内容,这里只是简单的介绍使用。

原文地址:https://www.cnblogs.com/pengjingya/p/14952103.html