OkHttp从使用到源代码分析(2)-请求的使用方法
之前說到OKHttp網(wǎng)絡(luò)請求支持兩種方式:同步請求和異步請求,同時(shí)又存在get和post請求,那么就是2*2,一共四種情況,接下來就分別介紹下這四種請求的使用和區(qū)別
在gradle中指定Java版本
compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8 }說到這里,需要補(bǔ)一點(diǎn),關(guān)于Android 9.0的http限制:默認(rèn)使用加密連接,Android P禁止 App 使用所有未加密的連接,因此 Android P 系統(tǒng)無論是接收或者發(fā)送流量,都不能明碼傳輸,需要使用下一代(Transport Layer Security)傳輸層安全協(xié)議,如果在Android P中使用http地址,將會出現(xiàn)如下錯(cuò)誤(這里使用的url為http://www.baidu.com)
W/System.err: java.net.UnknownServiceException: CLEARTEXT communication to www.baidu.com not permitted by network security policy
為了解決這個(gè)問題,常見的處理方式有三種:
- APP改用https請求
- targetSdkVersion 降到27(Android 8.1)以下
- 在 res 下新增一個(gè) xml 目錄,然后創(chuàng)建配置文件。再在application中添加進(jìn)來
同步請求
- get同步請求
此時(shí)得到的log如下(省略了html的一長串內(nèi)容):
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()),所以在使用的時(shí)候需要在子線程中運(yùn)行,同時(shí)response.body().string()其本質(zhì)上是對流的操作,也是需要在子線程中進(jìn)行。另外,返回碼中的code是在http中定義的,遵行http協(xié)議。由于response.body().string()的本質(zhì)是對流進(jìn)行操作,所以,在調(diào)用的時(shí)候,只會得到一次的返回值,再次調(diào)用會返回null,其根本原因是客戶端發(fā)出請求,服務(wù)端做出響應(yīng),將數(shù)據(jù)寫入到流中,客戶端得到返回值,再次調(diào)用時(shí)服務(wù)端并沒有在流中寫入數(shù)據(jù),此時(shí)客戶端就沒有數(shù)據(jù),得到的就為null。
- post同步請求
post與get同步請求的區(qū)別在與post是需要帶入請求體的,這也和get與post請求的本質(zhì)區(qū)別有關(guān)。
post需要構(gòu)建出請求體,從而完成post請求。
同步請求方法總結(jié):
異步請求
- get異步請求
使用注意:
回調(diào)接口位于子線程,即call.enqueue()會將網(wǎng)絡(luò)請求放在子線程中執(zhí)行,說到這,就該知道UI更新什么的該怎么使用了吧。
- post異步請求
嗯~~~,這個(gè)和上面的get異步請求差不多,區(qū)別在于post請求需要構(gòu)建RequestBody對象傳入post(),從而完成Request對象的構(gòu)建,其他也就沒啥區(qū)別了。
異步請求方法總結(jié):
- post參數(shù)說明
查看post的方法
可以看到傳入的參數(shù)為:RequestBody,那么這是個(gè)什么玩意兒呢?
其實(shí)就是請求體,再看看怎么構(gòu)建,查看源代碼會發(fā)現(xiàn)有五種靜態(tài)構(gòu)建方法
其源代碼如下
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,那么具體怎么構(gòu)建呢,以下舉出兩個(gè)例子
JSON格式上傳
FILE格式上傳
MediaType fileType = MediaType.parse("File/*"); //數(shù)據(jù)類型為file格式 File file = new File("/sdcard/test.txt"); RequestBody body = RequestBody.create(fileType, file);同時(shí)查看源代碼還發(fā)現(xiàn),RequestBody有兩個(gè)實(shí)現(xiàn)類,FormBody與MultipartBody,這兩個(gè)是OkHttp對RequestBody的實(shí)現(xiàn),前者用于傳遞鍵值對參數(shù),后者用于傳遞復(fù)雜參數(shù)。
例如使用FormBody傳遞鍵值對
使用MultipartBody的例子
MultipartBody multipartBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("title", "title") //鍵值對.addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("file/*"), file)) //文件.build();這里需要說明一點(diǎn),OkHttp并沒有實(shí)現(xiàn)文件的下載功能,但我們可以拿到流,那么也就是說可以將流轉(zhuǎn)化為文件保存,也就實(shí)現(xiàn)了文件下載功能。
熱門開源項(xiàng)目源代碼分析導(dǎo)航
總結(jié)
以上是生活随笔為你收集整理的OkHttp从使用到源代码分析(2)-请求的使用方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AOP。。。
- 下一篇: NLP之替换不在词表中的分词为‘UNK‘