OKHttp使用示例翻译和个人理解
来源:互联网 发布:金馆长ps软件 编辑:程序博客网 时间:2024/06/05 16:22
package dh.okhttp_demo;import android.os.Bundle;import android.os.Environment;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import com.google.gson.Gson;import java.io.File;import java.io.IOException;import java.util.Map;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;import okhttp3.Authenticator;import okhttp3.Cache;import okhttp3.Call;import okhttp3.Callback;import okhttp3.Credentials;import okhttp3.FormBody;import okhttp3.Headers;import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;import okhttp3.Route;import okio.BufferedSink;/** * 这个项目主要列举一下okhttp的常用用法 * 主要依据okhttp在github上提供的官方教程 * github教程地址:https://github.com/square/okhttp/wiki/Recipes * 在必要的地方写好注释,以便不时之需 * * 包括: * * 同步get * 异步get * 获取Headers * post一个字符串 * post一个流 * post一个文件 * post表单参数 * post多部分的请求 * 结合GSON解析json数据 * 响应缓存 * 取消请求 * timeout设置 * 请求前配置 * 处理身份验证 */public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private static final String TAG_CONTENT = "OK_HTTP"; private final OkHttpClient client = new OkHttpClient(); private final Gson gson = new Gson(); private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8"); private static final String IMGUR_CLIENT_ID = "9199fdef135c122"; private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.synchronous_get).setOnClickListener(this); 、、、其余的监听注册一样 } @Override public void onClick(View view) { switch (view.getId()) { case R.id.synchronous_get: { new Thread(new Runnable() { @Override public void run() { SynchronousGet(); } }).start(); } break; 、、、 //其余一样方法调用写法一样,在4.0后强制规定不能在UI线程发起网络请求 break; default:break; } } /** * 同步get,最普通的,顺序执行 * * 获取response的headers,name,value * 获取response的body信息 * 其中response.body().toString()会把body信息一次性加载到内存, * 所以这种方法只适合body大小小于1MB的 */ private void SynchronousGet() { Request request = new Request.Builder() .url("https://publicobject.com/helloworld.txt") .build(); try { Response response = client.newCall(request).execute(); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { Log.d(TAG_CONTENT, responseHeaders.name(i) + ":" + responseHeaders.value(i)); } Log.d(TAG_CONTENT, response.body().toString()); Log.d(TAG_CONTENT,"同步"); } catch (IOException e) { e.printStackTrace(); } } /** * 异步get * * 使用OKHttpClient的enqueue方法实现异步回调,另开一个线程下载文件, * 当response可读时回调接口 * 因为OKHttp没有提供读取response body时异步的API, * 回调完成后就回到了UI线程,所以解析response时可能阻塞UI线程 */ private void AsynchronousGet() { Log.d(TAG_CONTENT, "1"); Request request = new Request.Builder() .url("https://publicobject.com/helloworld.txt") .build(); /** * 匿名内部类实现callback */ Log.d(TAG_CONTENT, "2"); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.d(TAG_CONTENT, "3"); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { Log.d(TAG_CONTENT, responseHeaders.name(i) + ":" + responseHeaders.value(i)); } Log.d(TAG_CONTENT, response.body().toString()); Log.d(TAG_CONTENT,"异步"); } }); Log.d(TAG_CONTENT, "4"); } /** * 存取headers * * 一个典型的HTTP头(HTTP headers)类似于Map<String, String>,一个字段一个值或者没有值 * 少数headers允许多个值,例如Vary,OkHttp's APIs两者都能处理 * * 发送请求时: * 使用header(name, value)方法添加请求头(request headers),如果原来有该字段, * 那么直接覆盖原来的,原来对应的值就会被新值替换 * 使用addHeader(name, value)方法添加header,原来有没有该字段没有影响 * 接收返回信息时: * 使用header(name)方法返回最新的name对应的值,如果没有值,返回null * 使用headers(name)方法,以list的形式返回该字段对应的所有值。 */ private void AccessHeaders() { Request request = new Request.Builder() .url("https://api.github.com/repos/square/okhttp/issues") .header("User-Agent", "OkHttp Headers.java") .addHeader("Accept", "application/json; q=0.5") .addHeader("Accept", "application/vnd.github.v3+json") .build(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, "Server:" + response.header("Server")); Log.d(TAG_CONTENT, "Date:" + response.header("Date")); Log.d(TAG_CONTENT, "Vary:" + response.headers("Vary")); } catch (IOException e) { e.printStackTrace(); } } /** * post一个string * 指定postBody的类型为markdown,通过的post方法把postBody发送出去并转换为html文件 * 发送到web服务器 * 因为postBody是整个加载到内存中,所以大小不能超过1MB */ private void PostString() { String postBody = "" + "Releases\n" + "--------\n" + "\n" + " * _1.0_ May 6, 2013\n" + " * _1.1_ June 15, 2013\n" + " * _1.2_ August 11, 2013\n"; Request request = new Request.Builder() .url("https://api.github.com/markdown/raw") .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody)) .build(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, response.body().toString()); } catch (IOException e) { e.printStackTrace(); } } /** * post一个流 * 流以一个RequestBody对象的形式存在 * RequestBody的内容通过写入的方式生成 * 这里写入是通过okio中BufferedSink的writeUtf8方法 * 也可以用sdk的BufferedSink.outputStream()方法写入 */ private void PostStreaming() { RequestBody requestBody = new RequestBody() { @Override public MediaType contentType() { return MEDIA_TYPE_MARKDOWN; } @Override public void writeTo(BufferedSink sink) throws IOException { sink.writeUtf8("Number\n"); sink.writeUtf8("---------\n"); for (int i = 2; i <=997; i++) { sink.writeUtf8(String.format(" * %s = %s\n", i, factor(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(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, response.body().toString()); } catch (IOException e) { e.printStackTrace(); } } /** * post一个文件 * 使用文件作为RequestBody */ private void PostFile() { File file = new File(Environment.getExternalStorageDirectory(), "README.md"); Request request = new Request.Builder() .url("https://api.github.com/markdown/raw") .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file)) .build(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, response.body().toString()); } catch (IOException e) { e.printStackTrace(); } } /** * post表单元素 * 通过FormBody.Builder()方法创建一个类似于HTML<form>形式的RequestBody * 键值对将使用HTML兼容的URL编码形式进行编码 */ private void PostForm() { RequestBody formBody = new FormBody.Builder() .add("search", "Jurassic Park") .build(); Request request = new Request.Builder() .url("https://en.wikipedia.org/w/index.php") .post(formBody) .build(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, response.body().toString()); } catch (IOException e) { e.printStackTrace(); } } /** * post分块请求 * 使用MultipartBody.Builder()构建包含多个块的RequestBody,并且兼容HTML文件上传表单 * 每个块本身也是一个request body,也能定义自己的headers * 这些headers描述一个块,例如Content-Disposition,如果需要, * content-Length and Content-Type这些headers会被自动添加 */ private void PostMultipart() { RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("title", "Square logo") .addFormDataPart("image", "logo-square.png", RequestBody.create(MEDIA_TYPE_PNG, new File(Environment.getExternalStorageDirectory(), "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(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, response.body().toString()); } catch (IOException e) { e.printStackTrace(); } } /** * 配合GSON解析json * ResponseBody.charStream()方法使用响应头Content-Type去指定选择哪个字符集解码json数据 * 默认是UTF-8 */ private void ParseResponseWithGson() { Request request = new Request.Builder() .url("https://api.github.com/gists/c2a7c39532239ff261be") .build(); try { Response response = client.newCall(request).execute(); Gist gist = gson.fromJson(response.body().charStream(), Gist.class); for (Map.Entry<String, GistFile> entry : gist.files.entrySet()) { Log.d(TAG_CONTENT, entry.getKey()); Log.d(TAG_CONTENT, entry.getValue().content); } } catch (IOException e) { e.printStackTrace(); } } static class Gist { Map<String, GistFile> files; } static class GistFile { String content; } /** * 缓存response * 首先需要一个缓存路径,设置好缓存数据最大大小 * 不可以在同一个缓存目录下同时进行多个缓存,会出错 * 一般情况下,第一次调用时配置好缓存,其中OKHttpClient实例设置为final, * 之后在任意地方调用这个唯一实例即可 * * response缓存使用HTTP headers来进行所有配置 * 可以添加请求头(request header)设置缓存失效时间, * 例如Cache-Control: max-stale=3600,OKHttp认可这样的请求头 * 而我们的web服务器可以通过自己的响应头(response header), * 例如Cache-Control: max-age=9600设置缓存失效时间 * 如果以上两个同时被设置,那么以时间较长的为准,单位为秒,3600指3600秒,9600指9600秒 * * There are cache headers to force a cached response, force a network response, * or force the network response to be validated with a conditional GET. */ private void CacheResponse() { File file = new File(Environment.getExternalStorageDirectory(), "CacheFile"); int cacheSize = 10*1024*1024;//10MB Cache cache = new Cache(file, cacheSize); final OkHttpClient cacheClient = new OkHttpClient.Builder() .cache(cache) .build(); Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); String response1Body = ""; try { Response response1 = cacheClient.newCall(request).execute(); response1Body = response1.body().string(); Log.d(TAG_CONTENT, "Response 1 response: " + response1); Log.d(TAG_CONTENT, "Response 1 cache response: " + response1.cacheResponse()); Log.d(TAG_CONTENT, "Response 1 network response: " + response1.networkResponse()); } catch (IOException e) { e.printStackTrace(); } String response2Body = ""; try { Response response2 = client.newCall(request).execute(); response2Body = response2.body().string(); Log.d(TAG_CONTENT, "Response 2 response: " + response2); Log.d(TAG_CONTENT, "Response 2 cache response: " + response2.cacheResponse()); Log.d(TAG_CONTENT, "Response 2 network response: " + response2.networkResponse()); } catch (IOException e) { e.printStackTrace(); } Log.d(TAG_CONTENT, "Response 2 equals Response 1? " + response1Body.equals(response2Body)); } /** * 取消网络请求 * 使用call.cancel()方法取消一个进行中的网络请求 * 如果一个线程中正在进行发起一个request或者接收一个response,那么它将收到一个IOException * 使用这个可以强制结束同步或异步网络请求,特别是用户退出应用时,以节约网络资源 */ private void CancelCall() { Request request = new Request.Builder() // This URL is served with a 2 second delay. .url("http://httpbin.org/delay/2") .build(); final long startNano = System.nanoTime(); final Call call = client.newCall(request); executor.schedule(new Runnable() { @Override public void run() { System.out.printf("%.5f Canceling call.%n", (System.nanoTime() - startNano) / 1e9f); call.cancel(); System.out.printf("%.5f Canceled call.%n", (System.nanoTime() - startNano) / 1e9f); } },1, TimeUnit.SECONDS); System.out.printf("%.5f Executing call.%n", (System.nanoTime() - startNano) / 1e9f); try { Response response = call.execute(); System.out.printf("%.5f Call was expected to fail, but completed: %s%n", (System.nanoTime() - startNano) / 1e9f, response); } catch (IOException e) { System.out.printf("%.5f Call failed as expected: %s%n", (System.nanoTime() - startNano) / 1e9f, e); } } /** * 配置超时 * connectTimeout连接超时 * writeTimeout写入超时 * readTimeout读取超时 */ private void ConfigureTimeouts() { final OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); Request request = new Request.Builder() // This URL is served with a 2 second delay. .url("http://httpbin.org/delay/2") .build(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, "Response Completed: " + response); } catch (IOException e) { e.printStackTrace(); } } /** * 在发起一个网络请求前进行预配置 * * OKHttp支持所有HTTP client的配置,包括代理、超时设定、缓存等等 * 这里例子以配置readTimeOut为例 * * 其实就是创建一个个OKHttpClient变量,然后引用唯一的OKHttpClient实例client * 然后按需发送网络请求 */ private void PerCallSettings() { Request request = new Request.Builder() // This URL is served with a 1 second delay. .url("http://httpbin.org/delay/1") .build(); //创建一个新的引用 OkHttpClient copy1 = new OkHttpClient.Builder() .readTimeout(500, TimeUnit.MILLISECONDS) .build(); try { Response response = copy1.newCall(request).execute(); Log.d(TAG_CONTENT, "response 1 succeed: " + response); } catch (IOException e) { System.out.println("Response 1 failed: " + e); } //创建一个新的引用 OkHttpClient copy2 = client.newBuilder() .readTimeout(3000, TimeUnit.MILLISECONDS) .build(); try { Response response = copy2.newCall(request).execute(); System.out.println("Response 2 succeeded: " + response); } catch (IOException e) { System.out.println("Response 2 failed: " + e); } } /** * 证书验证 * * OKHttp会自动重试未验证的request * 当一个response包含401 Not Authorized信息,OKHttp的Authenticator接口会要求提供证书 * 实现接口的过程中应该创建一个新的要求提供缺失证书的request,没有可提供的证书则返回null * * 使用Response.challenges()获取方案和认证要求(authentication challenges) * 当履行一个基本的认证要求时, * 使用Credentials.basic(username, password)编码request header */ private void Authenticate() { final OkHttpClient client = new OkHttpClient.Builder() .authenticator(new Authenticator() { @Override public Request authenticate(Route route, Response response) throws IOException { /** * 也可以设定检查验证的次数,responseCount方法在最后 * if (responseCount(response) >= 3) { return null; // If we've failed 3 times, give up. } */ if (response.request().header("Authorization") != null) { // Give up, we've already attempted to authenticate. return null; } Log.d(TAG_CONTENT, "Authenticating for response: "+ response); Log.d(TAG_CONTENT, "Challenges: " + response.challenges()); String credential = Credentials.basic("jesse", "password1"); return response.request().newBuilder() .header("Authorization", credential) .build(); } }) .build(); Request request = new Request.Builder() .url("http://publicobject.com/secrets/hellosecret.txt") .build(); try { Response response = client.newCall(request).execute(); Log.d(TAG_CONTENT, response.body().string()); } catch (IOException e) { e.printStackTrace(); } } private int responseCount(Response response) { int result = 1; while ((response = response.priorResponse()) != null) { result++; } return result; }}
0 0
- OKHttp使用示例翻译和个人理解
- OkHttp Wiki翻译(一)使用OkHttp
- OkHttp和HttpUrlConnection的示例
- hive mapjoin 使用 和个人理解
- EGOTableViewPullRefresh个人理解代码原理和使用
- spring的AOP个人理解和使用
- hive mapjoin 使用 和个人理解
- degegate的理解和使用示例
- degegate的理解和使用示例
- okhttp2 和 okhttp 3上传单张或者多张图片的差异( 更好地理解使用okhttp )
- Learning a Deep Compact Image Representation for Visual Tracking的部分翻译和个人理解
- DataGridView 使用个人理解
- HandlerThread使用个人理解
- OkHttp的使用和封装
- okhttp使用详解和原理
- android 使用sqlite 和 okhttp
- OkHttp简易封装和使用
- OkHttp保存和使用cookie
- sublime安装插件不能安装上的一些解决方法
- 人脸识别性别识别 csv文件生成
- CentOS下的mysql安装
- 计算机基础之牛客网刷题第四篇
- 项目启动加载缓存
- OKHttp使用示例翻译和个人理解
- ubuntu kylin16.10谷歌输入法输入不了中文的解决办法
- python正则表达式简述
- centos7之lamp环境搭建
- 巧用mybatis 的<foreach>标签的 index 属性解决批量排序值问题
- Java反射机制demo
- git的基本使用方法
- HDU_2176 取(m堆)石子游戏
- 小程序微信支付java(来自技术小菜的分享)