国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

android okhttp的基礎使用【入門推薦】

2019-12-12 04:03:46
字體:
來源:轉載
供稿:網友

這篇文章主要總結Android著名網絡框架-okhttp的基礎使用,后續可能會有關于他的高級使用。

okhttp是什么

okhttp是Android端的一個Http客戶端,其基礎功能相當于Android自帶的HttpURLConnection和Apache HTTP Client,但他卻比自帶的2個Http客戶端優越很多,一者是寫法簡單,二者okhttp處理很多網絡復雜問題,如會從很多常用的連接問題中自動恢復。如果您的服務器配置了多個IP地址,當第一個IP連接失敗的時候,OkHttp會自動嘗試下一個IP。OkHttp還處理了代理服務器問題和SSL握手失敗等等很多問題。關于第二者,這篇文章不討論。

okhttp的導入

Gradle導入

 compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okio:okio:1.6.0'

okhttp基礎使用

這里我們主要介紹簡單的使用,介紹內容如下

  1. get請求
  2. post請求,參數是鍵值對
  3. post請求,多種類型的body
  4. 文件下載
  5. 加入Gson

get請求

get請求分為同步get和異步get,兩者的區別主要get的方式是工作在另一個線程還是工作在本線程。請求的方式大同小異。

首先定義一個OkHttpClient對象,如下

private OkHttpClient client = new OkHttpClient();

然后構建一個Request,構建方式如下:

Request request = new Request.Builder().url("http://www.baidu.com").build();

這個是最簡單的request的構建方式,當然我們可以構建的很復雜。

 Request request = new Request.Builder().    url("http://www.baidu.com").    addHeader("User-Agent","android").    header("Content-Type","text/html; charset=utf-8").    build();

通過addHeader和header方法為請求增加請求頭部,注意使用header(name, value)可以設置唯一的name、value。如果已經有值,舊的將被移除,然后添加新的。使用addHeader(name, value)可以添加多值(添加,不移除已有的)。

同步的get方法,通過client.newCall(request).execute()方法得到請求的response.

 Response response = okHttpClient.newCall(request).execute();

OkHttp封裝了很多處理response的方法,比如response.headers()的得到headers.

Headers headers = response.headers(); for (int i = 0; i < headers.size(); i++) {System.out.println(headers.name(i) + ": " + headers.value(i)); }

結果如下:

Date: Mon, 18 Apr 2016 05:23:43 GMTContent-Type: text/html; charset=utf-8Transfer-Encoding: chunkedConnection: Keep-AliveVary: Accept-EncodingSet-Cookie: BAIDUID=A323EC9BF678C0EB78E20741FD71211B:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.comSet-Cookie: BIDUPSID=A323EC9BF678C0EB78E20741FD71211B; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.comSet-Cookie: PSTM=1460957023; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.comSet-Cookie: BDSVRTM=0; path=/Set-Cookie: BD_HOME=0; path=/Set-Cookie: H_PS_PSSID=1434_19672_18281_19690_17948_18205_19558_15952_12257; path=/; domain=.baidu.comP3P: CP=" OTI DSP COR IVA OUR IND COM "Cache-Control: privateCxy_all: baidu+2db7793e0e32b9f6c20be8f623e1ae43Expires: Mon, 18 Apr 2016 05:22:55 GMTX-Powered-By: HPHPServer: BWS/1.1X-UA-Compatible: IE=Edge,chrome=1BDPAGETYPE: 1BDQID: 0xfacc6fc10004ca96BDUSERID: 0OkHttp-Sent-Millis: 1460957021226OkHttp-Received-Millis: 1460957021430

響應報文的實體可以通過response.body().string()獲取;如果希望獲得返回的二進制字節數組,則調用response.body().bytes();如果你想拿到返回的inputStream,則調用response.body().byteStream()。

異步的get請求得到的response方法是通過如下方法

okHttpClient.newCall(request).enqueue(new Callback() {      @Override      public void onFailure(Call call, IOException e) {      }        @Override      public void onResponse(Call call, Response response) throws IOException {      }    });

在onResponse方法中,執行請求成功的代碼,onFailure方法中,執行請求失敗的代碼,下面給一個完整的異步get的栗子

import android.os.Bundle;import android.os.Handler;import android.support.v7.app.AppCompatActivity;import android.text.method.ScrollingMovementMethod;import android.widget.TextView;import java.io.IOException;import okhttp3.Call;import okhttp3.Callback;import okhttp3.Headers;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;public class MainActivity extends AppCompatActivity { private OkHttpClient okHttpClient = new OkHttpClient(); public TextView show; public Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  show = (TextView) findViewById(R.id.show);  show.setMovementMethod(ScrollingMovementMethod.getInstance());  Request request = new Request.Builder().    url("http://www.baidu.com").    addHeader("User-Agent", "android").    header("Content-Type", "text/html; charset=utf-8").    get().    build();  okHttpClient.newCall(request).enqueue(new Callback() {   @Override   public void onFailure(Call call, IOException e) {   }   @Override   public void onResponse(Call call, final Response response) throws IOException {    final Headers headers = response.headers();    final String str = response.body().string();    handler.post(new Runnable() {     @Override     public void run() {      for (int i = 0; i < headers.size(); i++) {       show.append(headers.name(i) + ": " + headers.value(i));       show.append(str);      }     }    });   }  }); }}

其實按照官網說的,回調是發生在response 的headers準備好就發生的,所以有時候請求response的實體部分會發生阻塞。

post請求――鍵值對為參數。

post請求和get請求除了在構建request上面不同以外,在處理response上面都是一樣的,所以下面我們只討論一下post構建request,當然post也是支持同步post和異步post的,可以參考get方法。

在構建post的request時候,首先用FormBody.Builder去構建request的body部分,栗子如下,當然這是OKHttp3的方法.

FormBody.Builder builder = new FormBody.Builder();  for(int i = 0 ; i < key.size() ;i ++){   builder.add(key.get(i),value.get(i));  }  RequestBody body = builder.build();

builder中add的是要加入的參數鍵值對。得到要構造的body后用

Request request = new Request.Builder().url(url).post(body).build();

獲得請求的request,后面的操作就和get方法是一樣的,這里可以參考異步get的栗子,構建一個post的request.下面的寫法原封不變。

post請求--多種類型的body

上文已經說了post和get的用法主要在構建不同的request上面,所以接下來我們主要討論的也是如何構建request.

參考上面,我們首先要創建一個requestBody,我們可以用下面的方式去構建,當然這也是okhttp3的方法

MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

已表單上傳的形式去提交post。我們看一下builder的方法

 /** Add a part to the body. */ public Builder addPart(RequestBody body) {  return addPart(Part.create(body)); } /** Add a part to the body. */ public Builder addPart(Headers headers, RequestBody body) {  return addPart(Part.create(headers, body)); } /** Add a form data part to the body. */ public Builder addFormDataPart(String name, String value) {  return addPart(Part.createFormData(name, value)); } /** Add a form data part to the body. */ public Builder addFormDataPart(String name, String filename, RequestBody body) {  return addPart(Part.createFormData(name, filename, body)); }

從這里我們可以看出可以直接用 public Builder addFormDataPart(String name, String filename, RequestBody body)上傳一個File,最后一個參數是請求的實體,可以通過 RequestBody.create(final MediaType contentType, final File file) 獲得,而MediaType則可以通過下面方法獲得

//調用judgeType方法private static final MediaType MEDIA_TYPE = MediaType.parse(judgeType(fileName);//judge方法如下private String judgeType(String path) {  FileNameMap fileNameMap = URLConnection.getFileNameMap();  String contentTypeFor = fileNameMap.getContentTypeFor(path);  if (contentTypeFor == null) {   contentTypeFor = "application/octet-stream";  }  return contentTypeFor; }

由于我后臺能力比較渣,這里用一個官網的例子來實現一遍我剛才討論的方法。

MultipartBody.Builder builder = new MultipartBody.Builder()  .setType(MultipartBody.FORM)  .addFormDataPart("image", "logo-square.png",   RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")));RequestBody requestBody = builder.build(); Request request = new Request.Builder()  .header("Authorization", "Client-ID " +"9199fdef135c122")  .url("https://api.imgur.com/3/image")  .post(requestBody)  .build();

當然除了這個方法以外,調用如下方法也是可以的,我們可以利用name和filename自己構造Header傳上去。

public Builder addPart(Headers headers, RequestBody body) {  return addPart(Part.create(headers, body))

栗子如下:

builder.addPart(Headers.of("Content-Disposition", "form-data; name=/"" + name + "/"; filename=/"" + fileName + "/""),fileBody);

后面的寫法和上面類似,這樣我們就實現了文件上傳的寫法。

文件下載

剛才我們上面已經說了,希望獲得返回的二進制字節數組,則調用response.body().bytes();如果你想拿到返回的inputStream,則調用response.body().byteStream()。換句話說,文件的下載可以簡單的通過get請求,得到相應的response,在把他的實體轉換成二進制流寫入文件,就是實現了文件的下載。主要的寫法就是文件的讀寫,跟OKHttp關系不大,當然我們也可以用okio來實現文件的讀寫,這里水平有限就不介紹了。下面給一個簡單的例子。

private void _download(final String url, final String destFileDir, final ResultCallback callback) {  final Request request = new Request.Builder().url(url).build();  final Call call = okHttpClient.newCall(request);  call.enqueue(new Callback() {   @Override   public void onFailure(Call call, IOException e) {   }   @Override   public void onResponse(Call call, Response response) throws IOException {    InputStream is = null;    byte[] buf = new byte[2048];    int len = 0;    FileOutputStream fos = null;    try {     is = response.body().byteStream();     File file = new File(destFileDir, getFileName(url));     fos = new FileOutputStream(file);     while((len = is.read(buf)) != -1){      fos.write(buf,0,len);     }     fos.flush();     //....省略后續對已經保存的文件的操作    } catch (IOException e) {     e.printStackTrace();    }finally {     try {      if (is != null) is.close();     } catch (IOException e) {     }     try     {      if (fos != null) fos.close();     } catch (IOException e)     {     }    }   }  }); }

加入Gson

接下來,我們討論一個很實際的問題,Android的網絡請求一般不會去請求一個網站的Html,更多的是請求后臺接口的Json文件,所以我們用Gson來處理json的解析。這一部分和前面就不同了,前面多數講的是如何構建不同的request來得到response,而對響應的結果,處理都是一致的。但這里主要的寫法就是用Gson去處理response,而request的構建則根據上面介紹的方法去構建,無需改變。

Gson的導入

compile 'com.google.code.gson:gson:2.6.2'

比如我們后臺給出的api是這樣一個json文件

{ "status": 0, "intro": "你好", "shopName": "byhieg",  "message": "查詢成功",}

則我們可以簡單的構建這樣的一個Test.java文件,如下所示:

public class Test { /**  * status : 0  * intro : byhieg  * shopName : byhige  * message : 查詢成功  */ private int status; private String intro; private String shopName; private String message; public int getStatus() {  return status; } public void setStatus(int status) {  this.status = status; } public String getIntro() {  return intro; } public void setIntro(String intro) {  this.intro = intro; } public String getShopName() {  return shopName; } public void setShopName(String shopName) {  this.shopName = shopName; } public String getMessage() {  return message; } public void setMessage(String message) {  this.message = message; }}

在獲得到response之后,用如下代碼把Json文件解析成result對象。然后調用result對象的get方法就可以得到json文件中的intro的值和shopname的值,以及status和message.這里就不多介紹了

Test result = new Gson().fromJson(response.body().string,Test.class);

總結

簡單介紹了okHttp的使用,對于一些高級用法請關注下篇文章,本人水平有限,如有錯誤,還望指正。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持武林網!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 信阳市| 灵璧县| 牙克石市| 铁岭县| 灌南县| 泸水县| 吉木萨尔县| 新和县| 韶山市| 河津市| 浙江省| 石渠县| 屏东市| 锦屏县| 萨嘎县| 鄯善县| 大新县| 东乌珠穆沁旗| 雷州市| 临泽县| 青阳县| 正宁县| 西畴县| 白河县| 宁夏| 鄂尔多斯市| 闻喜县| 赞皇县| 凌源市| 邵阳县| 安顺市| 含山县| 凤庆县| 乐至县| 通山县| 淮南市| 肇东市| 太康县| 叶城县| 奇台县| 九龙坡区|