OKHTTP深入浅出(二)----基本用法

1 、引入

Gradle 引入依赖

implementation 'com.squareup.okhttp3:okhttp:3.14.7'
implementation 'com.squareup.okio:okio:1.17.5'

2、 Manifest 申请网络权限

 
 
 

3、基本用法

  1. 第一步: 构建OKHttpClient对象
  2. 第二步:构建Request请求对象
  3. 第三步:生成CALL对象
  4. 第四步:call 发起网络请求(同步/异步)

3.1 GET 同步请求

//1、构建okhttpClient 对象
OkHttpClient okHttpClient = new OkHttpClient();
// 2、 构建request请求对象
Request request = new Request.Builder().url("www.baidu.com").get().build();
// 3、生成call对象
Call call = okHttpClient.newCall(request);
// 4、 发起同步请求,同步请求要放在子线程中
 new Thread(new Runnable() {
            @Override
              public void run() {
                   try {
                        Response response = call.execute();
                    } catch (IOException e){
                        e.printStackTrace();
                    }
                }
  }).start();

3.2  GET 异步请求

如果要主线程中直接使用,不单独新建子线程,可以用异步请求.

 //1.构建okHttpClient对象
            OkHttpClient okHttpClient = new OkHttpClient();
            //2.构建request请求对象
            Request request = new Request.Builder().url("www.baidu.com").get().build();
            //3.生成call对象
            Call call = okHttpClient.newCall(request);
            //4.异步请求
            call.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    Log.e(TAG,"okhttp get enqueue:" + response.body().string());
                    ResponseBody body = response.body();
                    String string = body.string();
                    byte[] bytes = body.bytes();
                    InputStream inputStream = body.byteStream();
                }
            });

 call.enqueue会异步执行,其实,两个回调方法 onFailure 和onResponse都是执行在子线程的,因此想要执行UI操作,需要使用Handle切换到UI线程。

3.3 同步POST请求

 POST请求与GET请求的区别:在构造Requeset对象时,需要多构建一个RequestBody对象,来携带我们提交的数据。

           //1.构建okHttpClient对象
            OkHttpClient okHttpClient = new OkHttpClient();
            //2.构建RequestBody对象
            RequestBody body = new FormBody.Builder()
                    .add("ip", "58.188.54.36")
                    .build();
            //3.构建request请求对象,将RequestBody传入request对象
            Request request = new Request.Builder()
                    .url("www.baidu.com")
                    .post(body)
                    .build();
            //4.生成call对象
            Call call = okHttpClient.newCall(request);
            //5.同步请求
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Response response = call.execute();
                        Log.e(TAG, "okhttp POST execute" + response.body().string());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

 在构建Request的时候,将get()替换成post(body),并且传入requestBody实例.如果构建Request的时候,不指定请求方法时,默认为GET请求。

3.4 POST异步请求

//1.构建okHttpClient对象
            OkHttpClient okHttpClient = new OkHttpClient();
            //2.构建RequestBody对象
            RequestBody body = new FormBody.Builder()
                    .add("ip", "58.188.54.36")
                    .build();
            //3.构建request请求对象,将RequestBody传入request对象
            Request request = new Request.Builder()
                    .url("www.baidu.com")
                    .post(body)
                    .build();
            //4.生成call对象
            Call call = okHttpClient.newCall(request);
            //5.异步请求
            call.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    Log.e(TAG, "okhttp POST execute" + response.body().string());
                }
            });

3.5 异步上传文件

 //1.构建okHttpClient对象
            OkHttpClient okHttpClient = new OkHttpClient();
            //2.构建RequestBody对象
            //2.1 文件类型
            MediaType contentType = MediaType.parse("text/x-markdown;charset=utf-8");
            //2.2 文件内容 string
            String content = "xiaomi";
            RequestBody requestBody = RequestBody.create(contentType, content);
            //3.构建request请求对象,将RequestBody传入request对象
            Request request = new Request.Builder()
                    .url("www.baidu.com")
                    .post(requestBody)
                    .build();
            //4.生成call对象
            Call call = okHttpClient.newCall(request);
            //5.异步请求
            call.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {

                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    Log.e(TAG, "okhttp POST execute" + response.body().string());
                }
            });

打印结果

okHttpPost enqueue: 
     onResponse:Response{protocol=http/1.1, code=200, message=OK, url=https://api.github.com/markdown/raw}
     body:

xiaoomi

具体的文件上传示例

首先在SD卡里面创建一个xioami.txt文件,里面的内容为"okhttp"

 //1.构建okHttpClient对象
            OkHttpClient okHttpClient = new OkHttpClient();
            //2.构建RequestBody对象,
            //2.1 定义上传文件的文件类型
            MediaType contentType = MediaType.parse("text/x-markdown;charset=utf-8");
            //文件路径
            String filePath = "";
            //判断当前文件的类型
            if (Environment.getExternalStorageState().equals(contentType)) {
                filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
            } else {
                return null;
            }
            File file = new File(filePath, "xiaomi.txt");
            //2.2 创建requestBody,将文件传入
            RequestBody requestBody = RequestBody.create(contentType, file);
            //3.构建request请求对象,将RequestBody传入request对象
            Request request = new Request.Builder()
                    .url("www.baidu.com")
                    .post(requestBody)
                    .build();
            //4.生成call对象
            Call call = okHttpClient.newCall(request);
            //5.异步请求
            call.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {

                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    Log.e(TAG, "okhttp POST execute" + response.body().string());
                }
            });

看完之后,感觉有点懵逼,怎么构建RequestBody的时候,有的时候用 ReuqestBody.create()来构建,有的时候用FormBody构建?这是为什么呢?

 FormBody是RequestBody的子类,FromBody 用于提交表单键值对,能够满足我们平常大部分的开发需求。

//RequestBody:FormBody,表单键值对
RequestBody formBody = new FormBody.Builder()
        .add("username", "hfy")
        .add("password", "qaz")
        .build();

 当然除了FormBody之外,RequestBody还有一个子类---MultipartyBody,用于post请求提交复杂类型的请求体.复杂请求体可以同时包含多种类型的请求数据.

3.6 异步上传Multiparty 文件

  //1.构建okHttpClient对象
            OkHttpClient okHttpClient = new OkHttpClient();
            //2.构建RequestBody对象,
            //2.1 定义上传文件的文件类型
            MediaType contentType = MediaType.parse("text/x-markdown;charset=utf-8");
            MultipartBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("title", "xiaomi")
                    .addFormDataPart("dress", "kejiyuan")
                    .addFormDataPart("image", "xm.jpg", RequestBody.create(contentType,
                            new File("/sdcard/xiaomi.jpg")))
                    .build();
            //3.构建request请求对象,将RequestBody传入request对象
            Request request = new Request.Builder()
                    .url("www.baidu.com")
                    .post(requestBody)
                    .build();
            //4.生成call对象
            Call call = okHttpClient.newCall(request);
            //5.异步请求
            call.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {

                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    Log.e(TAG, "okhttp POST execute" + response.body().string());
                }
            });

   在构建RequestBody的时候,使用的MultipartyBody构建的MultipartBody实例,前两个上传的是键值对,第三个上传的是表单.addformDatapart方法的第一个参数是key,第二个是上传文件的名子,第三个参数是需要上传的文件。

3.7 请求配置项

问题:

1.如何全局设置超时时长?

2.缓存位置,最大缓存大小呢?

3.要监控App通过okhttp发送的所有请求,以及整个请求的所有耗时时间呢?

//1.构建okHttpClient对象
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .readTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(10, TimeUnit.SECONDS)
                    .cache(new Cache(new File("/sdcard/xiaomi.jpg"),500*1024*1024))
                    .addInterceptor(new Interceptor() {
                        @NotNull
                        @Override
                        public Response intercept(@NotNull Chain chain) throws IOException {
                            Request request = chain.request();
                            String url = request.url().toString();
                            Log.i(TAG, "intercept: proceed start: url"+ url+ ", at "+System.currentTimeMillis());
                            Response response = chain.proceed(request);
                            ResponseBody body = response.body();
                            Log.i(TAG, "intercept: proceed end: url"+ url+ ", at "+System.currentTimeMillis());
                            return response;
                        }
                    })
                    .build();

  这里通过OK HTTPClient.Builder构建者模式设置了连接,读取,写入的超时时间,缓存cache()方法传入了有缓存目录,缓存大小构成的Cache实例.

同时,使用addInterceptor()方法添加了interceptor实例,重写了interceptor方法.interceptor为拦截器,在执行请求的时候会调用,其中chain.procee(request) 是内部真正请求的过程,是个阻塞过程,执行完毕之后,就会得到response.所以在该前后去当时时间,就可以得知整个请求的耗时。

除了全局设置之外,还可以对单个请求进行设置.

Request request = new Request.Builder()
                    .url("www.baidu.com")
                    .post(requestBody)
                    .addHeader("key","value")
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build();

addHeader()方法添加了请求头

cacheControl(CacheControl.FORCE_NETWORK) 设置此次请求只能使用网络,不能用缓存.

3.8 取消请求

      使用call.cancel()可以立马取消一个正在执行的call.当用户离开一个应用时,或者跳转到其他的界面时,使用call.cancel()可以节约网络资源;此外,不管同步或者异步的call都可以取消,也可以通过tag来同时取消多个请求.但构建一个请求的时候,通过request.builder.tag()来分配一个标签,之后就可以用okhttpclient.cancel(tag)来取消所有带标签的请求.

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
    private void cancel() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        final Request request = new Request.Builder()
                .url("www.baidu.com")
                .cacheControl(CacheControl.FORCE_NETWORK)
                .build();
        Call call = okHttpClient.newCall(request);
        executorService.schedule(new Runnable() {
            @Override
            public void run() {
                call.cancel();
            }
        },10,TimeUnit.MICROSECONDS);
    }
 
call.enqueue(new Callback() {
    @Override
    public void onFailure(@NotNull Call call, @NotNull IOException e) {

    }

    @Override
    public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        if (response.cacheResponse() != null) {
            Log.e(TAG, "cache" + response.cacheResponse().toString());
        } else {
            Log.e(TAG, "network" + response.networkResponse().toString());
        }
    }
});   

参考:Android进阶之光

网络请求框架OkHttp3全解系列(一):OkHttp的基本使用

你可能感兴趣的:(Android,gradle,android,studio,android)