这篇文章说下OkHttp的基本用法,是最新的3哦,如果你曾经在网上搜索OkHttp怎么使用发现有些类没有了可能是因为人家说的是2。

首先说下OkHttp3是Java和Android都能用,Android还有一个著名网络库叫Volley,那个只有Android能用。

导入

自己到入jar包,别漏了okio:

okhttp-3.3.0.jarokio-1.8.0.jar

maven方式:

  com.squareup.okhttp3  okhttp  3.3.0

gradle方式:

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

Get请求

String url = "https://www.baidu.com/";OkHttpClient okHttpClient = new OkHttpClient();Request request = new Request.Builder()    .url(url)    .build();Call call = okHttpClient.newCall(request);try {    Response response = call.execute();    System.out.println(response.body().string());} catch (IOException e) {    e.printStackTrace();}

如果你需要在request的的header添加参数。例如Cookie,User-Agent什么的,就是

Request request = new Request.Builder()    .url(url)    .header("键", "值")    .header("键", "值")    ...    .build();

response的body有很多种输出方法,string()只是其中之一,注意是string()不是toString()。如果是下载文件就是response.body().bytes()。
另外可以根据response.code()获取返回的状态码。

Post请求

String url = "https://www.baidu.com/";OkHttpClient okHttpClient = new OkHttpClient();RequestBody body = new FormBody.Builder()    .add("键", "值")    .add("键", "值")    ...    .build();Request request = new Request.Builder()    .url(url)    .post(body)    .build();Call call = okHttpClient.newCall(request);try {    Response response = call.execute();    System.out.println(response.body().string());} catch (IOException e) {    e.printStackTrace();}

post请求创建request和get是一样的,只是post请求需要提交一个表单,就是RequestBody。表单的格式有好多种,普通的表单是:

RequestBody body = new FormBody.Builder()    .add("键", "值")    .add("键", "值")    ...    .build();

RequestBody的数据格式都要指定Content-Type,常见的有三种:

  • application/x-www-form-urlencoded 数据是个普通表单
  • multipart/form-data 数据里有文件
  • application/json 数据是个json

但是好像以上的普通表单并没有指定Content-Type,这是因为FormBody继承了RequestBody,它已经指定了数据类型为application/x-www-form-urlencoded。

private static final MediaType CONTENT_TYPE = MediaType.parse("application/x-www-form-urlencoded");

再看看数据为其它类型的RequestBody的创建方式。

如果表单是个json:

MediaType JSON = MediaType.parse("application/json; charset=utf-8");RequestBody body = RequestBody.create(JSON, "你的json");

如果数据包含文件:

RequestBody requestBody = new MultipartBody.Builder()    .setType(MultipartBody.FORM)    .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/png"), file))    .build();

上面的MultipartBody也是继承了RequestBody,看下源码可知它适用于这五种Content-Type:

public static final MediaType MIXED = MediaType.parse("multipart/mixed");public static final MediaType ALTERNATIVE = MediaType.parse("multipart/alternative");public static final MediaType DIGEST = MediaType.parse("multipart/digest");public static final MediaType PARALLEL = MediaType.parse("multipart/parallel");public static final MediaType FORM = MediaType.parse("multipart/form-data");

另外如果你上传一个文件不是一张图片,但是MediaType.parse("image/png")里的"image/png"不知道该填什么,可以参考下这个页面。

同步与异步

从上文已经能知道call.execute()就是在执行http请求了,但是这是个同步操作,是在主线程运行的。如果你在android的UI线程直接执行这句话就出异常了。
OkHttp也帮我们实现了异步,写法是:

String url = "https://www.baidu.com/";OkHttpClient okHttpClient = new OkHttpClient();Request request = new Request.Builder()        .url(url)        .build();Call call = okHttpClient.newCall(request);call.enqueue(new Callback() {    @Override    public void onFailure(Call call, IOException e) {        e.printStackTrace();    }    @Override    public void onResponse(Call call, Response response) throws IOException {        System.out.println("我是异步线程,线程Id为:" + Thread.currentThread().getId());    }});for (int i = 0; i < 10; i++) {    System.out.println("我是主线程,线程Id为:" + Thread.currentThread().getId());    try {        Thread.currentThread().sleep(100);    } catch (InterruptedException e) {        e.printStackTrace();    }}

执行结果是:

我是主线程,线程Id为:1我是主线程,线程Id为:1我是主线程,线程Id为:1我是异步线程,线程Id为:11我是主线程,线程Id为:1我是主线程,线程Id为:1我是主线程,线程Id为:1我是主线程,线程Id为:1我是主线程,线程Id为:1我是主线程,线程Id为:1我是主线程,线程Id为:1

显然onFailure()和onResponse()分别是在请求失败和成功时会调用的方法。这里有个要注意的地方,onFailure()和onResponse()是在异步线程里执行的,所以如果你在Android把更新UI的操作写在这两个方法里面是会报错的,这个时候可以用runOnUiThread这个方法。

自动管理Cookie

Request经常都要携带Cookie,上面说过request创建时可以通过header设置参数,Cookie也是参数之一。就像下面这样:

Request request = new Request.Builder()    .url(url)    .header("Cookie", "xxx")    .build();

然后可以从返回的response里得到新的Cookie,你可能得想办法把Cookie保存起来。
但是OkHttp可以不用我们管理Cookie,自动携带,保存和更新Cookie。
方法是在创建OkHttpClient设置管理Cookie的CookieJar:

private final HashMap> cookieStore = new HashMap<>();OkHttpClient okHttpClient = new OkHttpClient.Builder()    .cookieJar(new CookieJar() {        @Override        public void saveFromResponse(HttpUrl httpUrl, List list) {            cookieStore.put(httpUrl.host(), list);        }        @Override        public List loadForRequest(HttpUrl httpUrl) {            List cookies = cookieStore.get(httpUrl.host());            return cookies != null ? cookies : new ArrayList();        }    })    .build();

这样以后发送Request都不用管Cookie这个参数也不用去response获取新Cookie什么的了。还能通过cookieStore获取当前保存的Cookie。
最后,new OkHttpClient()只是一种快速创建OkHttpClient的方式,更标准的是使用OkHttpClient.Builder()。后者可以设置一堆参数,例如超时时间什么的。

更多相关文章

  1. Android 使用后台线程
  2. Android进程与线程
  3. android跨线程通信eventbus
  4. android子线程不能更新UI
  5. android异步线程为什么有这个错呢!
  6. Android的进程与线程模型
  7. android消息机制,异步和多线程

随机推荐

  1. 如何在亿级数据中判断一个元素是否存在?
  2. android ProgressBar 样式讲解
  3. Android(安卓)Java List 排序
  4. Android简易Flash播放器
  5. Android(安卓)LiveData 使用详解
  6. 在Android模拟器中模拟GPS、打电话、发短
  7. XX for Android(安卓)Design 设计文档
  8. android stduio gradle参数配置说明
  9. Android(安卓)unbindservice异常相关问题
  10. HttpClient 多线程