OkHttp使用

来源:互联网 发布:域名转入万网和阿里云 编辑:程序博客网 时间:2024/05/28 04:53

配置

compile 'com.squareup.okhttp3:okhttp:3.4.1'

GET

首先是以同步的方式执行请求

//创建一个requestRequest request = new Request.Builder()        .url(url)        .build();Response response = client.newCall(request).execute();if (response.isSuccessful()) {  //请求成功    Log.d(TAG, "testGet: " + response.body().string());} else {    throw new IOException("" + response.code());}

以上就是执行GET请求的方法。

  1. 构造一个Request对象,参数最起码有个url,当然你可以通过Request.Builder设置更多的参数比如:header、method等。
  2. 通过request的对象去构造得到一个Call对象,类似于将你的请求封装成了任务,既然是任务,就会有execute()和cancel()等方法。
  3. 当前我们使用的是同步的方法,即调用call的execute()方法。若希望以异步的方式去执行请求,我们可以调用call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。
  4. onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。
  5. 图片下载,通过回调的Response拿到byte[]然后decode成图片;文件下载,就是拿到inputStream做写文件操作。

异步执行请求

call.enqueue(new Callback(){    //请求失败    @Override    public void onFailure(Request request, IOException e)    {    }    //得到响应时    @Override    public void onResponse(final Response response) throws IOException    {        //String htmlStr =  response.body().string();    }});

为Request添加请求头

 Request request = new Request.Builder()         .url("http://www.baidu.com")         .addHeader("User-Agent","android")         .header("Content-Type","text/html; charset=utf-8")         .build();

若想要为GET请求添加参数的话可以使用HttpUrl类来构造url

HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();urlBuilder.addQueryParameter("KEY", "VALUE");HttpUrl httpUrl = urlBuilder.build();

POST

post请求的执行也可以同步或者异步,参考GET请求。简便起见,这里默认用同步方法。

POST 提交json字符串

设置MediaType

MediaType mediaType = Medi2aType.parse("application/json; charset=utf-8");

执行post请求

private Response post(String url, String json) throws IOException {    RequestBody requestBody = RequestBody.create(mediaType, json);    Request request = new Request.Builder()            .url(url)            .post(requestBody)            .build();    Response response = client.newCall(request).execute();        return response;}
  1. 通过RequestBody.create(MediaType contentType, String content)方法来构造RequestBody, contentType代表了上传内容的类型,content即上传的json字符串
  2. 使用Request的post方法来提交请求体RequestBody

POST 提交键值对

很多时候我们需要向服务器提交键值对。这是构造RequestBody的方法就与上面说的不同了。当然,这里介绍的时OkHttp3的方法
1. 通过FormBody.Builder()创建一个构造器,它的add()方法添加键值对,再通过build方法来构造一个FormBody。
2. FormBody的父类为RequestBody,所以我们可以将FormBody作为请求体使用。

RequestBody formBody = new FormBody.Builder()        .add("name1", "value1")        .add("name2", "value2")        .build();

POST 以流的形式

public static final MediaType MEDIA_TYPE_MARKDOWN      = MediaType.parse("text/x-markdown; charset=utf-8");  private final OkHttpClient client = new OkHttpClient();  public void run() throws Exception {    RequestBody requestBody = new RequestBody() {      //设置ContentType      @Override      public MediaType contentType() {        return MEDIA_TYPE_MARKDOWN;      }      @Override      public void writeTo(BufferedSink sink) throws IOException {        sink.writeUtf8("Numbers\n");        sink.writeUtf8("-------\n");        for (int i = 2; i <= 997; i++) {          sink.writeUtf8(String.format(" * %s = %s\n", i, (i)));        }      }      private String factor(int n) {        for (int i = 2; i < n; i++) {          int x = n / i;          if (x * i == n) return factor(x) + " × " + i;        }        return Integer.toString(n);      }    };    Request request = new Request.Builder()        .url("https://api.github.com/markdown/raw")        .post(requestBody)        .build();    Response response = client.newCall(request).execute();    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);    System.out.println(response.body().string());  }

这里直接向Buffered Sink中写入流,若更喜欢使用OutputStream,请使用BufferedSink.outputStream()

POST 上传文件

public static final MediaType MEDIA_TYPE_MARKDOWN      = MediaType.parse("text/x-markdown; charset=utf-8");  private final OkHttpClient client = new OkHttpClient();  public void run() throws Exception {    File file = new File("README.md");    Request request = new Request.Builder()        .url("https://api.github.com/markdown/raw")        .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))        .build();    Response response = client.newCall(request).execute();    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);    System.out.println(response.body().string());  }

若不确定文件的类型,可通过以下方法获得文件类型

private static final MediaType MEDIA_TYPE = MediaType.parse(judgeType(fileName);private String judgeType(String path) {        FileNameMap fileNameMap = URLConnection.getFileNameMap();        String contentTypeFor = fileNameMap.getContentTypeFor(path);        if (contentTypeFor == null) {            contentTypeFor = "application/octet-stream";        }        return contentTypeFor;    }

POST 多种类型的body

通过MultipartBody.addPart(),MultipartBody.addFormDataPart()实现。每个Part都是它所属的RequestBody的一个请求体,因此,它们也可以拥有自己的headers。通过MultipartBody.setType()方法,可以设置MultipartBody的类型

private static final String IMGUR_CLIENT_ID = "...";  private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");  private final OkHttpClient client = new OkHttpClient();  public void run() throws Exception {    // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image    RequestBody requestBody = new MultipartBody.Builder()        .setType(MultipartBody.FORM)        .addFormDataPart("title", "Square Logo")        .addFormDataPart("image", "logo-square.png",            RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))        .build();    Request request = new Request.Builder()        .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)        .url("https://api.imgur.com/3/image")        .post(requestBody)        .build();    Response response = client.newCall(request).execute();    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);    System.out.println(response.body().string());  }

提取响应头

典型的HTTP头 像是一个Map<String, String>每个字段都有一个或没有值。但是一些头允许多个值,像Guava的Multimap。例如:HTTP响应里面提供的Vary响应头,就是多值的。OkHttp的api试图让这些情况都适用。
当写请求头的时候,使用header(name, value)可以设置唯一的name、value。如果已经有值,旧的将被移除,然后添加新的。使用addHeader(name, value)可以添加多值(添加,不移除已有的)。
当读取响应头时,使用header(name)返回最后出现的name、value。通常情况这也是唯一的name、value。如果没有值,那么header(name)将返回null。如果想读取字段对应的所有值,使用headers(name)会返回一个list。

参考

Android OkHttp完全解析 是时候来了解OkHttp了
OkHttp使用进阶 译自OkHttp Github官方教程
okhttp教程——起步篇
OkHttp使用教程

0 0