Okhttp的基本使用

前言

okhttp无疑Android端最火热的网络请求框架了,由Square公司贡献。
下面对以OKHttp3来介绍OKHttp的使用方法。
本人菜鸡水平,写此文章为了加深印象,如果发现错误或不足恳请指正。谢谢

异步和同步的区别

同步请求:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步请求:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式


来张图

添加依赖

 implementation 'com.squareup.okhttp3:okhttp:4.2.1'
 implementation 'com.squareup.okio:okio:2.2.2'

okio依赖必须有不然会报错

get请求

我们先看一下异步请求

      //获取client
        OkHttpClient client=new OkHttpClient.Builder().build();
        //构建request,这里不写方法的话默认为get()
        Request request=new Request.Builder()
                .url("http://www.baidu.com")
                .build(); //最后一定要build一下
        //构建Call
        Call call=client.newCall(request);
        //异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                Log.d(TAG,"onFailure");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                Log.d(TAG,response.body().string());
                Log.d(TAG,Thread.currentThread().getName());
            }
        });

我们看这个最简单的demo
LoginActivity123: OkHttp http://www.baidu.com/...
logcat打印出来这句话,说明了回调接口的onFailure方法和onResponse执行在子线程,如果想进行UI操作,还需把消息发到主线程进行

我们在看同步的请求

new Thread(new Runnable() {
            @Override
            public void run() {
                //获取client
                OkHttpClient client=new OkHttpClient.Builder().build();
                //构建request,这里不写方法的话默认为get()
                Request request=new Request.Builder()
                        .url("http://www.baidu.com")
                        .build(); //最后一定要build一下
                //构建Call
                Call call=client.newCall(request);
                //同步请求
                try {
                    Response response = call.execute();
                    if (response.isSuccessful()){
                        Log.d(TAG,"responsecode:"+response.code());
                        Log.d(TAG,"responseMsg:"+response.message());
                        Log.d(TAG,"res:"+response.body().string());
                        //此时在子线程,更新UI需要在主线程
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

我们可以看到,前三个步骤和异步请求的方式一样,有区别的地方就是call这个对象执行的方法是enqueue还是execute。
需要注意的:response.body().string()方法也必须放在子线程中。当执行这行代码得到结果后,再跳转到UI线程修改UI

post请求

post请求也分同步请求和异步请求,和get请求的同步异步类似,我们在开发中,用到的大多数是异步请求,所以我们只看一下异步的请求。

//获取client
        OkHttpClient client = new OkHttpClient.Builder()
                .build();
        //创建RequestBody(Form表单)
        RequestBody body = new FormBody.Builder()
                .add("username", "admin")
                .add("password", "123456")
                .build();
        //构建建Rquest
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        //构建Call
        final Call call = client.newCall(request);
        //发起请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "onFailure");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                Log.i(TAG, "onResponse");
            }
        });

这里我们需要注意的是,当请求方式为post请求时,我们需要把请求方式进行设置,就是post这个方法,并且我们需要请求对象传进去。这里是把表单请求体对象作为post方法的参数。我们来看看这几种:
1.使用FormBody传递键值对参数
这种方式用来上传String类型的键值对
2.使用RequestBody传递Json

     MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式,
     String jsonStr = "{\"username\":\"admin\",\"password\":\"123456\"}";//json数据.
     RequestBody body1 = RequestBody.create(JSON,jsonStr);

3.使用RequestBody传递File

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

4.使用MultipartBody同时传递键值对和File对象

MultipartBody multipartBody =new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("groupId","123")//添加键值对参数
                .addFormDataPart("username","admin")
                .addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("file/*"), file))//添加文件
                .build();

以上的这几种方法都是构建requestBody的方法,实现了传递不能类型的对象。

文件下载

        InputStream is = null;
        FileOutputStream fos = null;
        try{
            is = response.body().byteStream();//从服务器得到输入流对象
            long sum = 0;
            File dir = new File("path");
            if (!dir.exists()){
                dir.mkdirs();
            }
            File file = new File(dir, filename);//根据目录和文件名得到file对象
            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();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (is!=null)
                is.close();
            if (fos!=null)
                fos.close();
        }

Response中可以获取流对象,有了流对象我们就可以自己实现文件的下载,在最后的finally语句块中要把流对象close。

总结

1.response.body().string()本质是输入流的读操作,这行代码必须放在子线程。
2.response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。
3.异步请求不需要开启子线程,enqueue方法会自动将网络请求部分放入子线程中执行。


感谢阅读,欢迎点赞评论!

你可能感兴趣的:(Okhttp的基本使用)