OkHttp
本文属于android网络编程课程里的系列文章之一
详情请查看网络编程课程
前面我们学习了http协议,然后使用java的api去访问网络,需要准备请求头,设置好各种东西,自己处理线程。会不会很麻烦呢?
于是,很多前辈觉得这样子很麻烦,就把这些复杂的东西封装起来,我们通过简单的调用,就可以实现网络请求了。

优点的话去看官网吧,这里就写成中文的了
- 请求同一主机的时候,一般是指同一域名,支持共享同一个socket
- 通过连接池减少请求延时
- 传输通过GZIP压缩,减少下载内容的体积
- 用缓存的方式避免重复的请求
应用场景
学习一门技术,从应用场景上手是最快的。毕竟你要落实到用处的嘛。
OkHttp在我们android开发中有哪些使用场景呢?
- 请求内容数据(目前来说,数据格式主要是json,xml比较少用了)
- 加载图片(一般来说,图片地址以内容的形式返回到手机端,然后再通过图片地址进行加载到控件中)
- 上传文件/数据(头像的上传,采集数据的上传,甚至是录像之类的大文件上传)
使用
api文档
这里我们使用到的api文档是商城的api文档
后面我们也会开放更多的文档
关于高版本(27以上)http访问的配置
如果访问为https协议的话,略过即可
如果在android27以上,默认是不支持Http访问的了,需要使用https,如果你要使用Http明文访问,那么需要配置一下。
在清单文件,application节点,添加
      android:networkSecurityConfig="@xml/network_security_config"
network_security_config
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">sunofbeaches.com</domain>
        <domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">www.sunofbeach.net</domain>
            <domain includeSubdomains="true">imgs.sunofbeaches.com</domain>
        </domain-config>
    </domain-config>
</network-security-config>
关于网络安全配置文件的说明请看这篇文章
声明权限
    <uses-permission android:name="android.permission.INTERNET" />
添加依赖
    implementation("com.squareup.okhttp3:okhttp:4.2.2")
异步get请求
步骤:
- 创建OkHttpClient
- 创建请求内容
- 浏览器根据请求内容创建请求任务
- 执行请求任务
代码:
 public void asyncGet(View view) {
        //获取商城的分类信息
        String url = "https://www.sunofbeach.net/shop/api/discovery/categories";
        //1、创建client,理解为创建浏览器
        OkHttpClient okHttpClient = new OkHttpClient();
        //2、创建请求内容
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        //3、用浏览器创建调用任务
        Call call = okHttpClient.newCall(request);
        //4、执行任务
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call,@NotNull IOException e) {
                Log.d(TAG,"onFailure -- > " + e.toString());
            }
            @Override
            public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
                Log.d(TAG,"response -- > " + response.body().string());
            }
        });
    }
执行结果:

同步的get请求
步骤跟前面一样,只是在执行任务的时候,不是异步的。
同步的请求,需要自己处理线程的问题,不可以在UI线程去执行任务。
代码
  public void syncGet(View view) {
        //获取商城的分类信息
        String url = "https://www.sunofbeach.net/shop/api/discovery/categories";
        //1、创建client,理解为创建浏览器
        OkHttpClient okHttpClient = new OkHttpClient();
        //2、创建请求内容
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        //3、用浏览器创建调用任务
        final Call call = okHttpClient.newCall(request);
        //4、执行任务
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Response response = call.execute();
                    Log.d(TAG,"response -- > " + response.body().string());
                } catch(IOException e) {
                    e.printStackTrace();
                    Log.d(TAG,"failure -- > " + e.toString());
                }
            }
        }).start();
    }
post请求
++举一反三呀++,对吧!前面get请求,在创建请求的时候.get(),那么post呢?
我们也有post请求的方法
测试一下商城的搜索接口
https://www.sunofbeach.net/shop/api/search/page
page是页码
参数:keyword
 public void doSearch(View view) {
        String url = "https://www.sunofbeach.net/shop/api/search/1";
        RequestBody requestBody = new FormBody.Builder()
                .add("keyword","电脑")
                .build();
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call,@NotNull IOException e) {
                Log.d(TAG,"onFailure -- > " + e.toString());
            }
            @Override
            public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
                Log.d(TAG,"response json --> " + response.body().string());
            }
        });
    }
可以看到,上面requestBody是FormBody,我们看看RequestBody的继承关系:

除了表单数据以外,还可以是文件。
学习神器SOBAndroidMiniWeb
程序地址:
具体的使用方法请看里面的文档说明。有了这个神器,我们就可以做接下来的网络学习了。
post上传单文件
使用场景:
比如说我们上传头像,比如说我们上传log
权限
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
一般来说, 我们读取的数据在扩展卡里,所以要加上这个权限。
比如说我们上传一张图片试试看。之前我们不是有imagePicker嘛,同学们可以结合那个案例去整一个,我这里为了比较快一点,我就直接复制一张图片到特定目录下了。
关于读取图片的动态权限获取请看这里:
    public void postFile(View view) {
        String url = "https://10.0.2.2:9102/file/upload";
        OkHttpClient httpClient = new OkHttpClient.Builder().build();
        File file = new File("/storage/emulated/0/Download/1.jpg");
        MediaType mediaType = MediaType.parse("image/jpeg");
        RequestBody fileBody = RequestBody.create(file,mediaType);
        RequestBody requestBody = new MultipartBody.Builder()
                .addFormDataPart("file",file.getName(),fileBody)
                .build();
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Call call = httpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call,@NotNull IOException e) {
                Log.d(TAG,"上传失败--> " + e.toString());
            }
            @Override
            public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
                Log.d(TAG,"上传结果:" + response.body().string());
            }
        });
    }
类型可以查看这里
上传结果:
{"success":true,"code":10000,"message":"上传成功.文件路径为:E:\\sobCourse\\sobAndroidWeb\\SOBAndroidMiniWeb\\sobUpload\\1.jpg","data":null}
查看路径上的图片:

多文件上传
那如何上传多文件呢?
在web程序里,我定义的接口
/file/upload
为单文件上传 而多文件上传的接口为 参数Kye为:file
/files/upload
为多文件上传 参数key为 files
上传代码:
 public void postMultiFile(View view) {
        String url = "https://10.0.2.2:9102/files/upload";
        OkHttpClient httpClient = new OkHttpClient.Builder().build();
        File fileOne = new File("/storage/emulated/0/Download/1.jpg");
        File fileTwo = new File("/storage/emulated/0/Download/rBsADV3nxtKACoSfAAAPx8jyjF8169.png");
        File fileThree = new File("/storage/emulated/0/Download/rBsADV2rEz-AIzSoAABi-6nfiqs456.png");
        MediaType mediaType = MediaType.parse("image/jpeg");
        RequestBody fileOneBody = RequestBody.create(fileOne,mediaType);
        RequestBody fileTwoBody = RequestBody.create(fileTwo,mediaType);
        RequestBody fileThreeBody = RequestBody.create(fileThree,mediaType);
        RequestBody requestBody = new MultipartBody.Builder()
                .addFormDataPart("files",fileOne.getName(),fileOneBody)
                .addFormDataPart("files",fileTwo.getName(),fileTwoBody)
                .addFormDataPart("files",fileThree.getName(),fileThreeBody)
                .build();
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Call call = httpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call,@NotNull IOException e) {
                Log.d(TAG,"多文件上传失败--> " + e.toString());
            }
            @Override
            public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
                Log.d(TAG,"多文件上传结果:" + response.body().string());
            }
        });
    }
结果:
{"success":true,"code":10000,"message":"上传成功3个文件,路径:E:/sobCourse/sobAndroidWeb/SOBAndroidMiniWeb/sobUpload","data":null}

好啦,学习android知道这些基本上够用了。知道怎么请求数据,怎么样上传数据。任务就这两个。
至于下载那些也是一样的,本质还是一个请求任务,而内容则在response里头,读取出来写入文件即可。这些我们都会在后面的案例里有。同学们先掌握这些先。代码一定要写。如果遇到问题,就发帖子交流吧。



 拉大锯  回复 @guiogiugijkkuoy
 拉大锯  回复 @guiogiugijkkuoy 






















