Okhttp 处理了很多网络疑难杂症,比如从很多常用的连接问题中自动恢复。如果你服务器配置了多个IP地址,当一个IP地址连接失败后Okhttp会自动尝试下一个IP,从Android4.4版本后,系统内置了Okhttp,可见Okhttp功能的强大。
远程依赖添加,okio作为Okhttp的IO组件,也是必须要引入的。
api 'com.squareup.okhttp3:okhttp:3.12.13'
api 'com.squareup.okio:okio:2.8.0'
Request.Builder url = new Request.Builder().url(""); url.method("GET", null); Request build = url.build(); OkHttpClient okHttpClient = new OkHttpClient(); Call call = okHttpClient.newCall(build); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { String string = response.body().string(); } });
其基本步骤就是创建OkhttpClient、Request、和Call,最后调用Call的enqueue方法,需要注意的是onResponse回调并非在UI线程中,如果想要同步GET请求,则可以调用Call的execute方法。
Okhttp3的异步POST请求和okhttp2的异步POST请求有一些差别,就是没有FormEncodingBuilder这个类,替代它的是功能强大的FormBody。
RequestBody formBody = new FormBody.Builder() .add("ip", "59.108.54.37") .build(); Request build = new Request.Builder() .url("") .post(formBody) .build(); OkHttpClient okHttpClient = new OkHttpClient(); Call call = okHttpClient.newCall(build); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
这与异步GET请求类似,只是多了FormBody来封装请求参数,并传递给Request
上传文件本身也是一个POST请求,首先定义上传的文件类型。
public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
在SD卡的根目录创建一个文件 ,里面内容为OkHttp
String filePath = ""; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { filePath = Environment.getExternalStorageDirectory().getAbsolutePath(); } else { return; } File file = new File(filePath, "test.txt"); Request build = new Request.Builder() .url("") .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file)) .build(); OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.newCall(build).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
如果想要改为同步上传文件,只要调用OkhttpClient.newCall(request).execute()就可以了,最终请求返回结构就是我们txt文件中的内容。
下载一张图片,得到Respouse后流写进我们指定的图片文件中,代码如下所示
String url = ""; Request request = new Request.Builder().url(url).build(); OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { InputStream inputStream = response.body().byteStream(); FileOutputStream fileOutputStream = null; String filePath = ""; try { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { filePath = Environment.getExternalStorageDirectory().getAbsolutePath(); } else { filePath = getFilesDir().getAbsolutePath(); } File file = new File(filePath, "test.jpg"); if (null != file) { fileOutputStream = new FileOutputStream(file); byte[] buffer = new byte[2048]; int len = 0; while ((len = inputStream.read(buffer)) != -1) { fileOutputStream.write(buffer, 0, len); } fileOutputStream.flush(); } } catch (Exception e) { e.printStackTrace(); } } });
有时上传文件时,同时还需要上传其他类型的字段。 Okhttp3 实现起来很简单。 需要注意的是没有服务器接受我这个Multipart文件,具体应用还要结合实际工作中对应的服务器
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); public static void send() { OkHttpClient okHttpClient = new OkHttpClient(); MultipartBody build = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("title", "test") //1 .addFormDataPart("image", "test.jpg", RequestBody.create(MEDIA_TYPE_PNG, new File("/sdcard/test.jpg")))//2 .build(); Request authorization = new Request.Builder() .header("Authorization", "Client-ID" + "...") .url("") .post(build) .build(); okHttpClient.newCall(authorization).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } }); }
上述代码中,注释1处是常见的 key-value(键-值)形式的参数。
注释2处则是上传表单,addFormDataPart方法的第一个参数是key值,第二个参数是上传文件的名字,第三个参数是需要上传的文件。
和Okhttp2有区别的是Okhttp3不能通过OkhttpClient直接设置超时时间和缓存了,而是通过OkHttpClient.Builder来设置。通过OkHttpClient.Builder配置好OkHttpClient后用builder.build()返回OkHttpClient。我们通常不会调用 new OkhttpClient() 来得到OkhttpClient,而是通过builder.build()得到OkHttpClient。另外OkHttp3支持设置连接,写入和读取超时时间。
File sdcache = new File(""); int cacheSize = 10 * 1024 * 1024; OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .writeTimeout(20, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS) .cache(new Cache(sdcache.getAbsoluteFile(),cacheSize)); OkHttpClient okHttpClient = builder.build();