OkHttp从使用到源代码分析(2)-请求的使用方法
之前說到OKHttp網絡請求支持兩種方式:同步請求和異步請求,同時又存在get和post請求,那么就是2*2,一共四種情況,接下來就分別介紹下這四種請求的使用和區別
在gradle中指定Java版本
compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8 }說到這里,需要補一點,關于Android 9.0的http限制:默認使用加密連接,Android P禁止 App 使用所有未加密的連接,因此 Android P 系統無論是接收或者發送流量,都不能明碼傳輸,需要使用下一代(Transport Layer Security)傳輸層安全協議,如果在Android P中使用http地址,將會出現如下錯誤(這里使用的url為http://www.baidu.com)
W/System.err: java.net.UnknownServiceException: CLEARTEXT communication to www.baidu.com not permitted by network security policy
為了解決這個問題,常見的處理方式有三種:
- APP改用https請求
- targetSdkVersion 降到27(Android 8.1)以下
- 在 res 下新增一個 xml 目錄,然后創建配置文件。再在application中添加進來
同步請求
- get同步請求
此時得到的log如下(省略了html的一長串內容):
D/NetworkSecurityConfig: Using Network Security Config from resource network_security_config debugBuild: true E/MainActivity: response code ==> 200 E/MainActivity: response message ==> OK E/MainActivity: response res ==> <!DOCTYPE html><!--STATUS OK--><html> ··· </html>使用注意:
由于同步請求是阻塞線程的(call.execute()),所以在使用的時候需要在子線程中運行,同時response.body().string()其本質上是對流的操作,也是需要在子線程中進行。另外,返回碼中的code是在http中定義的,遵行http協議。由于response.body().string()的本質是對流進行操作,所以,在調用的時候,只會得到一次的返回值,再次調用會返回null,其根本原因是客戶端發出請求,服務端做出響應,將數據寫入到流中,客戶端得到返回值,再次調用時服務端并沒有在流中寫入數據,此時客戶端就沒有數據,得到的就為null。
- post同步請求
post與get同步請求的區別在與post是需要帶入請求體的,這也和get與post請求的本質區別有關。
post需要構建出請求體,從而完成post請求。
同步請求方法總結:
異步請求
- get異步請求
使用注意:
回調接口位于子線程,即call.enqueue()會將網絡請求放在子線程中執行,說到這,就該知道UI更新什么的該怎么使用了吧。
- post異步請求
嗯~~~,這個和上面的get異步請求差不多,區別在于post請求需要構建RequestBody對象傳入post(),從而完成Request對象的構建,其他也就沒啥區別了。
異步請求方法總結:
- post參數說明
查看post的方法
可以看到傳入的參數為:RequestBody,那么這是個什么玩意兒呢?
其實就是請求體,再看看怎么構建,查看源代碼會發現有五種靜態構建方法
其源代碼如下
public abstract class RequestBody {···/*** Returns a new request body that transmits {@code content}. If {@code contentType} is non-null* and lacks a charset, this will use UTF-8.*/public static RequestBody create(@Nullable MediaType contentType, String content) {Charset charset = UTF_8;if (contentType != null) {charset = contentType.charset();if (charset == null) {charset = UTF_8;contentType = MediaType.parse(contentType + "; charset=utf-8");}}byte[] bytes = content.getBytes(charset);return create(contentType, bytes);}/** Returns a new request body that transmits {@code content}. */public static RequestBody create(final @Nullable MediaType contentType, final ByteString content) {return new RequestBody() {@Override public @Nullable MediaType contentType() {return contentType;}@Override public long contentLength() throws IOException {return content.size();}@Override public void writeTo(BufferedSink sink) throws IOException {sink.write(content);}};}/** Returns a new request body that transmits {@code content}. */public static RequestBody create(final @Nullable MediaType contentType, final byte[] content) {return create(contentType, content, 0, content.length);}/** Returns a new request body that transmits {@code content}. */public static RequestBody create(final @Nullable MediaType contentType, final byte[] content,final int offset, final int byteCount) {if (content == null) throw new NullPointerException("content == null");Util.checkOffsetAndCount(content.length, offset, byteCount);return new RequestBody() {@Override public @Nullable MediaType contentType() {return contentType;}@Override public long contentLength() {return byteCount;}@Override public void writeTo(BufferedSink sink) throws IOException {sink.write(content, offset, byteCount);}};}/** Returns a new request body that transmits the content of {@code file}. */public static RequestBody create(final @Nullable MediaType contentType, final File file) {if (file == null) throw new NullPointerException("file == null");return new RequestBody() {@Override public @Nullable MediaType contentType() {return contentType;}@Override public long contentLength() {return file.length();}@Override public void writeTo(BufferedSink sink) throws IOException {try (Source source = Okio.source(file)) {sink.writeAll(source);}}};} }常用的RequestBody有json與file,那么具體怎么構建呢,以下舉出兩個例子
JSON格式上傳
FILE格式上傳
MediaType fileType = MediaType.parse("File/*"); //數據類型為file格式 File file = new File("/sdcard/test.txt"); RequestBody body = RequestBody.create(fileType, file);同時查看源代碼還發現,RequestBody有兩個實現類,FormBody與MultipartBody,這兩個是OkHttp對RequestBody的實現,前者用于傳遞鍵值對參數,后者用于傳遞復雜參數。
例如使用FormBody傳遞鍵值對
使用MultipartBody的例子
MultipartBody multipartBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("title", "title") //鍵值對.addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("file/*"), file)) //文件.build();這里需要說明一點,OkHttp并沒有實現文件的下載功能,但我們可以拿到流,那么也就是說可以將流轉化為文件保存,也就實現了文件下載功能。
熱門開源項目源代碼分析導航
總結
以上是生活随笔為你收集整理的OkHttp从使用到源代码分析(2)-请求的使用方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AOP。。。
- 下一篇: MS SQLServer 2008数据库