日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OkHttp从使用到源代码分析(2)-请求的使用方法

發布時間:2024/1/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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中添加進來
<?xml version="1.0" encoding="utf-8"?> <network-security-config><base-config cleartextTrafficPermitted="true" /> </network-security-config> android:networkSecurityConfig="@xml/network_security_config"

同步請求

  • get同步請求
private void synGetRequest() {new Thread(new Runnable() {@Overridepublic void run() {OkHttpClient mClient = new OkHttpClient.Builder().callTimeout(5, TimeUnit.SECONDS) //設置超時時間.build(); //構建OkHttpClient對象Request request = new Request.Builder().url("http://www.baidu.com") //請求url.get() //默認請求方式,寫不寫都是get.build(); //創建Request對象Call call = mClient.newCall(request); //構建Call對象try {Response response = call.execute(); //得到Response對象if(response.isSuccessful()) {Log.e(TAG, "response code ==> " + response.code());Log.e(TAG, "response message ==> " + response.message());Log.e(TAG, "response res ==> " + response.body().string());}else {Log.e(TAG, "response fail");}} catch (IOException e) {e.printStackTrace();}}}).start(); }

此時得到的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同步請求
private void synPostRequest() {new Thread(new Runnable() {@Overridepublic void run() {OkHttpClient mClient = new OkHttpClient.Builder().callTimeout(5, TimeUnit.SECONDS) //設置超時時間.build(); //構建OkHttpClient對象MediaType JSON = MediaType.parse("application/json; charset=utf-8"); //數據類型為json格式,String json = "{\"username\":\"chen\"}"; //json數據RequestBody body = RequestBody.create(JSON, json); //創建RequestBody對象Request request = new Request.Builder().url("http://www.baidu.com") //請求url.post(body) //post請求方式,需要傳入RequestBody對象.build(); //創建Request對象Call call = mClient.newCall(request); //構建Call對象try {Response response = call.execute(); //得到Response對象if (response.isSuccessful()) {Log.e(TAG, "response code ==> " + response.code());Log.e(TAG, "response message ==> " + response.message());Log.e(TAG, "response res ==> " + response.body().string());} else {Log.e(TAG, "response fail");}} catch (IOException e) {e.printStackTrace();}}}).start(); }

post與get同步請求的區別在與post是需要帶入請求體的,這也和get與post請求的本質區別有關。
post需要構建出請求體,從而完成post請求。

同步請求方法總結:

  • 創建OkHttpClient和Request對象
  • 將Request封裝成Call對象
  • 調用Call的execute()方法發送同步請求
  • 異步請求

    • get異步請求
    private void asyGetRequest() {OkHttpClient mClient = new OkHttpClient.Builder().callTimeout(5, TimeUnit.SECONDS) //設置超時時間.build(); //構建OkHttpClient對象Request request = new Request.Builder().url("https://www.baidu.com").get().build();Call call = mClient.newCall(request);call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) { //請求失敗回調Log.e(TAG, "onFailure ===> " + e.getMessage());}@Overridepublic void onResponse(Call call, Response response) throws IOException { //請求成功回調Log.e(TAG, "onResponse ===> " + response.body().string());}}); }

    使用注意:
    回調接口位于子線程,即call.enqueue()會將網絡請求放在子線程中執行,說到這,就該知道UI更新什么的該怎么使用了吧。

    • post異步請求
      嗯~~~,這個和上面的get異步請求差不多,區別在于post請求需要構建RequestBody對象傳入post(),從而完成Request對象的構建,其他也就沒啥區別了。

    異步請求方法總結:

  • 創建OkHttpClient和Request對象
  • 將Request封裝成Call對象
  • 調用Call的enqueue()方法進行異步請求
    • post參數說明
      查看post的方法
    public Builder post(RequestBody body) {return method("POST", body); }

    可以看到傳入的參數為:RequestBody,那么這是個什么玩意兒呢?
    其實就是請求體,再看看怎么構建,查看源代碼會發現有五種靜態構建方法

    RequestBody.create(MediaType, String) RequestBody.create(MediaType, ByteString) RequestBody.create(MediaType, byte[]) RequestBody.create(MediaType, byte[], int, int) RequestBody.create(MediaType, File)

    其源代碼如下

    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格式上傳

    MediaType JSON = MediaType.parse("application/json; charset=utf-8"); //數據類型為json格式 String json = "{\"username\":\"chen\"}"; RequestBody body = RequestBody.create(JSON, 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傳遞鍵值對

    RequestBody body = new FormBody.Builder() //創建表單請求.add("username","chen").add("from","PC").build();

    使用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)-请求的使用方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。