欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android网络请求OKHttp详解

程序员文章站 2022-04-08 11:37:36
在android studio中引入包 compile ‘com.squareup.okhttp3:okhttp:3.4.1’ 具体使用? okhttp提供异步请求跟同步...

android studio中引入包

compile ‘com.squareup.okhttp3:okhttp:3.4.1’

具体使用?
okhttp提供异步请求跟同步请求,android中主要用到异步请求

一、get的异步请求

public void get() {
    okhttpclient client = new okhttpclient();
    request request = new request.builder()
            .url("https://www.baidu.com")
            .build();
    client.newcall(request).enqueue(new callback() {
        @override
        public void onfailure(call call, ioexception e) {
           logutils.w("获取数据失败了");
        }

        @override
        public void onresponse(call call, response response) throws ioexception {
            logutils.w("获取数据成功了");
            logutils.w("response.code()==" + response.code());
            logutils.w("response.body().string()==" + response.body().string());
        }
    });
}

返回结果

获取数据成功了
response.code()==200
response.body().string()=={....}

注意?
- 回调接口的onfailure方法和onresponse执行在子线程?
- response.code是http响应行中的code,如果访问成功则返回200.这个不是服务器设置的,而是http协议中状态码?
- response.body().string()本质是输入流的读操作,所以它还是网络请求的一部分,所以这行代码必须放在子线程?
- response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。因为response.body().string()的本质是输入流的读操作,必须有服务器的输出流的写操作时客户端的读操作才能得到数据。而服务器的写操作只执行一次,所以客户端的读操作也只能执行一次,第二次将返回null

二、post异步请求

public void post() {
    okhttpclient client = new okhttpclient();//创建okhttpclient对象。
    formbody.builder formbody = new formbody.builder();//创建表单请求体
    formbody.add("username", "zhangsan");//传递键值对参数
    request request = new request.builder()//创建request 对象。
            .url("https://www.baidu.com")
            .post(formbody.build())//传递请求体
            .build();
    client.newcall(request).enqueue(new callback() {
        @override
        public void onfailure(call call, ioexception e) {
            //回调方法的使用与get异步请求相同
        }

        @override
        public void onresponse(call call, response response) throws ioexception {
            //回调方法的使用与get异步请求相同
        }
    });
}
okhttp中没有设置get/post请求方式,默认是get请求,当调用post(formbody.build())时自动修改请求方式为post

三、post请求参数传递方式

使用request.builder类中的post(requestbody body)方法传递

post方法接收的参数是requestbody 对象,所以只要是requestbody 类以及子类对象都可以当作参数进行传递。formbody就是requestbody 的一个子类对象

使用formbody传递键值对参数

public void postdatawithparame() {
    okhttpclient client = new okhttpclient();//创建okhttpclient对象。
    formbody.builder formbody = new formbody.builder();//创建表单请求体
    formbody.add("username","zhangsan");//传递键值对参数
    request request = new request.builder()//创建request 对象。
            .url("https://www.baidu.com")
            .post(formbody.build())//传递请求体
            .build();
    client.newcall(request).enqueue(new callback() {。。。});//此处省略回调方法。
}

使用requestbody传递json或file对象

requestbody是抽象类,故不能直接使用,但是他有静态方法create,使用这个方法可以得到requestbody对象

这种方式可以上传json对象或file对象?
上传json对象使用示例如下

okhttpclient client = new okhttpclient();//创建okhttpclient对象。
mediatype json = mediatype.parse("application/json; charset=utf-8");//数据类型为json格式,
string jsonstr = "{\"username\":\"lisi\",\"nickname\":\"李四\"}";//json数据.
requestbody body = requestbody.create(json, josnstr);
request request = new request.builder()
        .url("https://www.baidu.com")
        .post(body)
        .build();
client.newcall(request).enqueue(new callback() {。。。});//此处省略回调方法。

上传file对象使用示例如下

okhttpclient client = new okhttpclient();//创建okhttpclient对象。
mediatype filetype = mediatype.parse("file/*");//数据类型为json格式,
file file = new file("path");//file对象.
requestbody body = requestbody.create(filetype , file );
request request = new request.builder()
        .url("https://www.baidu.com")
        .post(body)
        .build();
client.newcall(request).enqueue(new callback() {。。。});//此处省略回调方法。

使用multipartbody同时传递键值对参数和file对象

okhttpclient client = new okhttpclient();
multipartbody multipartbody =new multipartbody.builder()
        .settype(multipartbody.form)
        .addformdatapart("groupid",""+groupid)//添加键值对参数
        .addformdatapart("title","title")
        .addformdatapart("file",file.getname(),requestbody.create(mediatype.parse("file/*"), file))//添加文件
        .build();
final request request = new request.builder()
        .url(urlcontant.chat_room_subject_image)
        .post(multipartbody)
        .build();
client.newcall(request).enqueue(new callback() {。。。});

自定义requestbody实现流的上传

requestbody body = new requestbody() {
    @override
    public mediatype contenttype() {
        return null;
    }

    @override
    public void writeto(bufferedsink sink) throws ioexception {//重写writeto方法
        fileinputstream fio= new fileinputstream(new file("filename"));
        byte[] buffer = new byte[1024*8];
        if(fio.read(buffer) != -1){
             sink.write(buffer);
        }
    }
};

四、设置请求头

request request = new request.builder()
                .url("https://www.baidu.com")
                .header("user-agent", "okhttp headers.java")
                .addheader("token", "mytoken")
                .build();

五、下载文件

在okhttp中并没有提供下载文件的功能,但是在response中可以获取流对象,有了流对象我们就可以自己实现文件的下载,在回调接口callback的onresponse方法中调用

try{
    inputstream  is = response.body().bytestream();//从服务器得到输入流对象
    long sum = 0;
    file dir = new file(mdestfiledir);
    if (!dir.exists()){
        dir.mkdirs();
    }
    file file = new file(dir, mdestfilename);//根据目录和文件名得到file对象
    fileoutputstream  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();
    return file;
}