Android 網路框架 OKHttp 學習
OKHttp
okHttp: OKHttp是Android版Http客戶端。非常高效,支援SPDY、連線池、GZIP和 HTTP 快取。預設情況下,OKHttp會自動處理常見的網路問題,像二次連線、SSL的握手問題。如果你的應用程式中整合了OKHttp,Retrofit預設會使用OKHttp處理其他網路層請求。
An HTTP & SPDY client for Android and Java applications 從Android4.4開始HttpURLConnection的底層實現採用的是okHttp.
使用要求:對於Android:2.3以上,對於Java:java7以上 兩個模組: okhttp-urlconnection實現.HttpURLConnection API; okhttp-apache實現Apache HttpClient API. 依賴:okio(https://github.com/square/okio): Okio, which OkHttp uses for fast I/O and resizable buffers.
安裝:
maven:
com.squareup.okhttpokhttp2.3.0
Gradle:
compile 'com.squareup.okhttp:okhttp:2.3.0'
GET A URL
同步GET:
private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url(http://publicobject.com/helloworld.txt) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException(Unexpected code + response); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { System.out.println(responseHeaders.name(i) + : + responseHeaders.value(i)); } System.out.println(response.body().string()); }
非同步GET:
在一個工作執行緒中下載檔案,當響應可讀時回撥Callback介面。讀取響應時會阻塞當前執行緒。OkHttp現階段不提供非同步api來接收響應體。
private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url(http://publicobject.com/helloworld.txt) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Request request, Throwable throwable) { throwable.printStackTrace(); } @Override public void onResponse(Response response) throws IOException { if (!response.isSuccessful()) throw new IOException(Unexpected code + response); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { System.out.println(responseHeaders.name(i) + : + responseHeaders.value(i)); } System.out.println(response.body().string()); } }); }
訪問Header:
private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { 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(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException(Unexpected code + response); System.out.println(Server: + response.header(Server)); System.out.println(Date: + response.header(Date)); System.out.println(Vary: + response.headers(Vary)); }
POST TO A SERVER
Posting a String:
public static final MediaType jsonReq = MediaType.parse(application/json; charset=utf-8); OkHttpClient client = new OkHttpClient(); String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(jsonReq, json); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }
Posting Streaming:
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() { @Override public MediaType contentType() { return MEDIA_TYPE_MARKDOWN; } @Override public void writeTo(BufferedSink sink) throws IOException { sink.writeUtf8(Numbers ); sink.writeUtf8(------- ); for (int i = 2; i <= 997; i++) { sink.writeUtf8(String.format( * %s = %s , 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(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException(Unexpected code + response); System.out.println(response.body().string()); }
Posting a File:
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()); }
Posting from parameters:
private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { RequestBody formBody = new FormEncodingBuilder() .add(search, Jurassic Park) .build(); Request request = new Request.Builder() .url(https://en.wikipedia.org/w/index.php) .post(formBody) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException(Unexpected code + response); System.out.println(response.body().string()); }
Posting a multipart request:
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 MultipartBuilder() .type(MultipartBuilder.FORM) .addPart( Headers.of(Content-Disposition, form-data; name= itle), RequestBody.create(null, Square Logo)) .addPart( Headers.of(Content-Disposition, form-data; name=image), 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()); }
Posing Json with Gson
private final OkHttpClient client = new OkHttpClient(); private final Gson gson = new Gson(); public void run() throws Exception { Request request = new Request.Builder() .url(https://api.github.com/gists/c2a7c39532239ff261be) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException(Unexpected code + response); Gist gist = gson.fromJson(response.body().charStream(), Gist.class); for (Map.Entry entry : gist.files.entrySet()) { System.out.println(entry.getKey()); System.out.println(entry.getValue().content); } } static class Gist { Map files; } static class GistFile { String content; }
Response Caching:
為了快取響應,你需要一個你可以讀寫的快取目錄,和快取大小的限制。這個快取目錄應該是私有的,不信任的程式應不能讀取快取內容。
一個快取目錄同時擁有多個快取訪問是錯誤的。大多數程式只需要呼叫一次 new OkHttp() ,在第一次呼叫時配置好快取,然後其他地方只需要呼叫這個例項就可以了。否則兩個快取示例互相干擾,破壞響應快取,而且有可能會導致程式崩潰。
響應快取使用HTTP頭作為配置。你可以在請求頭中新增 Cache-Control: max-stale=3600 ,OkHTTP快取會支援。你的服務通過響應頭確定響應快取多長時間,例如使用 Cache-Control: max-age=9600 。
private final OkHttpClient client; public CacheResponse(File cacheDirectory) throws Exception { int cacheSize = 10 * 1024 * 1024; // 10 MiB Cache cache = new Cache(cacheDirectory, cacheSize); client = new OkHttpClient(); client.setCache(cache); } public void run() throws Exception { Request request = new Request.Builder() .url(http://publicobject.com/helloworld.txt) .build(); Response response1 = client.newCall(request).execute(); if (!response1.isSuccessful()) throw new IOException(Unexpected code + response1); String response1Body = response1.body().string(); System.out.println(Response 1 response: + response1); System.out.println(Response 1 cache response: + response1.cacheResponse()); System.out.println(Response 1 network response: + response1.networkResponse()); }
Canceling a Call
final Call call = client.newCall(request); call.cancel();
Timeouts:
private final OkHttpClient client; public ConfigureTimeouts() throws Exception { client = new OkHttpClient(); client.setConnectTimeout(10, TimeUnit.SECONDS); client.setWriteTimeout(10, TimeUnit.SECONDS); client.setReadTimeout(30, TimeUnit.SECONDS); }
Handling Authentication:
private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { client.setAuthenticator(new Authenticator() { @Override public Request authenticate(Proxy proxy, Response response) { System.out.println(Authenticating for response: + response); System.out.println(Challenges: + response.challenges()); String credential = Credentials.basic(jesse, password1); return response.request().newBuilder() .header(Authorization, credential) .build(); } @Override public Request authenticateProxy(Proxy proxy, Response response) { return null; // Null indicates no attempt to authenticate. } }); Request request = new Request.Builder() .url(http://publicobject.com/secrets/hellosecret.txt) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException(Unexpected code + response); System.out.println(response.body().string()); }
為避免當驗證失敗時多次重試,我們可以通過返回null來放棄驗證:
if (responseCount(response) >= 3) { return null; // If we've failed 3 times, give up. } //新增以下方法 private int responseCount(Response response) { int result = 1; while ((response = response.priorResponse()) != null) { result++; } return result; }
Interceptors
class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); logger.info(String.format(Sending request %s on %s%n%s, request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); long t2 = System.nanoTime(); logger.info(String.format(Received response for %s in %.1fms%n%s, response.request().url(), (t2 - t1) / 1e6d, response.headers())); return response; } }
Application Interceptors:
OkHttpClient client = new OkHttpClient(); client.interceptors().add(new LoggingInterceptor());
Network Interceptors
OkHttpClient client = new OkHttpClient(); client.networkInterceptors().add(new LoggingInterceptor());
相關文章
- Android網路請求(3) 網路請求框架OkHttpAndroid框架HTTP
- Android 網路框架之OKhttp實現https請求Android框架HTTP
- Andriod 網路框架 OkHttp 原始碼解析框架HTTP原始碼
- okhttp網路請求框架的簡單使用HTTP框架
- android開發之網路學習-Socket學習Android
- Retrofit和OkHttp實現 Android網路快取HTTPAndroid快取
- Android okHttp網路請求之Json解析AndroidHTTPJSON
- Android okHttp網路請求之Get/Post請求AndroidHTTP
- Android精通之OrmLite資料庫框架,Picasso框架,Okio框架,OKHttp框架AndroidORM資料庫框架HTTP
- Android開源框架原始碼鑑賞:OkhttpAndroid框架原始碼HTTP
- Android okHttp網路請求之檔案上傳下載AndroidHTTP
- 網路安全需要學習哪些技能?網路安全學習
- Android之Mina框架學習Android框架
- Android八門神器(一):OkHttp框架原始碼解析AndroidHTTP框架原始碼
- Android網路請求(終) 網路請求框架RetrofitAndroid框架
- Flutter學習(7)——網路請求框架Dio簡單使用Flutter框架
- Android 網路框架 Retrofit 原始碼解析Android框架原始碼
- 手寫Android網路框架——CatHttp(一)Android框架HTTP
- 手寫Android網路框架——CatHttp(二)Android框架HTTP
- OKHttp網路請求原理流程解析HTTP
- Android 學習路線圖Android
- Android OkHttp3原始碼詳解——整體框架AndroidHTTP原始碼框架
- Android網路請求(4) 網路請求框架VolleyAndroid框架
- 網路安全需要學習哪些內容?網路安全線上學習
- 網路安全學習技巧有哪些?網路安全學習要多久?
- 專案重構之網路篇 根據OkHttp封裝簡單的框架HTTP封裝框架
- Android 網路優化,使用 HTTPDNS 優化 DNS,從原理到 OkHttp 整合Android優化httpdDNS
- Android okHttp網路請求之快取控制Cache-ControlAndroidHTTP快取
- 網路安全工程師課件流行框架,最新學習路線圖工程師框架
- Android Http請求框架二:xUtils 框架網路請求AndroidHTTP框架
- 網路安全學習有些啥市場價值?網路安全學習
- 零基礎如何學習網路安全?網路安全學習方法
- 學習網路安全需要基礎嗎?網路安全內容學習
- Android 網路框架Retrofit的使用和解析Android框架
- Android 網路框架Volley JAR包生成Android框架JAR
- OKHttp原始碼學習--HttpURLConnection HttpClient OKHttp Get and post Demo用法對比HTTP原始碼client
- 如何學習網路安全
- 【AIX 學習】網路管理AI