Android 開發 框架系列 OkHttp使用詳解

簡介

okhttp是一個第三方類庫,用於android中請求網絡。這是一個開源項目,是安卓端最火熱的輕量級框架,由移動支付Square公司貢獻(該公司還貢獻了Picasso和LeakCanary) 。用於替代HttpUrlConnection和Apache HttpClient(android API23 裏已移除HttpClient)。android

依賴

implementation 'com.squareup.okhttp3:okhttp:3.11.0'



 

同步請求方式(get請求)

步驟一  建立請求接口網址

我使用了http://www.sosoapi.com/ 來建立了一個訪問接口,用來驗證OkHttp是否請求成功。若是你有興趣瞭解,能夠直接進入網站,裏面有詳細的demo演示。後續我將不在贅述這段。git

我在請求響應裏添加了一段JSON數據:github

[
    {
        "name": "get測試",
        "content": "你成功獲取了數據"
    }
]

步驟二  建立JSON解析方法

這裏我寫一下解析JSON數據的方法,來解析get或者post獲得的JSON數據。後續我將不在贅述這段。json

/**
     * JSON 解析方法
     * @param jsonData
     * @return
     */
    public String readJSONContent(String jsonData){
        try {
            StringBuffer sb = new StringBuffer();
            JSONArray jsonArray = new JSONArray(jsonData);
            for (int i=0;i<jsonArray.length();i++){
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                sb.append(jsonObject.getString("name")+"\n");
                sb.append(jsonObject.getString("content")+"\n");
            }
            return sb.toString();
        } catch (JSONException e) {
            Log.e("JSONException錯誤", "readContent: "+e.toString());
            return e.toString();
        }
    }

步驟三  建立OkHttp 同步請求

/**
     * 同步請求
     */
    public void synchro(){
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient okHttpClient = new OkHttpClient();//建立單例
                Request request = new Request.Builder()//建立請求
                        .url("http://www.sosoapi.com/pass/mock/12003/test/gettest")
                        .build();
                try {
                    Response response = okHttpClient.newCall(request).execute();//執行請求
                    mContent = response.body().string();//獲得返回響應

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mtextView.setText(readJSONContent(mContent));
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("OkHttpActivity", e.toString() );
                }
            }
        });
        thread.start();
    }

效果圖:

 

 


 

異步請求方式(get請求)

注意1:異步請求方式,請求的回調會在子線程裏,因此若是須要更新UI你須要切換到主線程。且你不須要在new 一個線程包裹這個異步請求了。另外如何切換到主線程請使用 Handler 例子:api

注意2:在異步請求方法裏,請不要將 public void onResponse(Call call, final Response response)回調裏的response回調數據放到UI線程裏解析,由於有一個天坑,有可能在UI線程裏解析的時候response裏面卻尚未塞入數據(我也以爲很神奇,不知道寫okhttp的公司是怎麼想的,爲何不處理完全部數據在提供回調)網絡

 

private Handler mHandler = new Handler(Looper.getMainLooper());
            mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //主線程

                    }
                });    

建立異步請求app

     /**
     * get異步請求
     */
      public void asynchronous(){
          OkHttpClient okHttpClient = new OkHttpClient();
          Request request = new Request.Builder()
                  .url("http://www.sosoapi.com/pass/mock/12003/test/gettest")
                  .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 {
            mContent = readJSONContent(response.body().string());
//響應成功,這個回調在子線程中,因此不須要建立線程 if (response.isSuccessful()){ //isSuccessful方法:若是代碼位於(200…300)中,則返回true,這意味着請求已成功接收 runOnUiThread(new Runnable() { @Override public void run() { try { //由於在子線程,因此咱們須要回到主線程中更新UI數據 mtextView.setText(mContent); } catch (IOException e) { e.printStackTrace(); } } }); } } }); }

 


 

Post請求

post請求也同時有同步與異步方法,與上面一致,因此這裏就不展現了,下面咱們來看看post請求發送框架

/**
     * post請求
     */
    public void post(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                //實例
                OkHttpClient okHttpClient = new OkHttpClient();

                //建立post請求數據表單
                RequestBody requestBody = new FormBody.Builder()
                        .add("name","請求post")
                        .add("password","123456")
                        .build();
                //建立請求
                final Request request = new Request.Builder()
                        .url("http://www.sosoapi.com/pass/mock/12003/test/posttest")
                        .post(requestBody)//添加post請求
                        .build();

                try {
                    //發送請求獲得響應
                    final Response response = okHttpClient.newCall(request).execute();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                mtextView.setText(readJSONContent(response.body().string()));
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }

效果圖:異步

取消網絡請求

取消okhttp的網絡請求很簡單隻須要async

call.cancel();

如何鑑別是網絡異常仍是主動取消,請求取消的回調在onFailure(Call call, IOException e)裏回調,這個時候咱們須要再次判斷onFailure裏回調的是咱們本身主動取消的仍是網絡異常報錯的

mCall.enqueue(new Callback() {//發送請求
    @Override
    public void onFailure(final Call call, final IOException e) {
        if (call.isCanceled()){
            listener.onCancel();

        }else {
            listener.onFailure(call, e);
        }
    }     
//省略下面代碼...

 


 

 

RequestBody建立

RequestBody是okhttp  post發送數據配置類.在這以前咱們先了解下回顧一下body類型

 

http有四種body類型,Content-Type POST提交數據的方式:
  • application/x-www-form-urlencoded 表單數據
  • multipart/form-data 表單文件上傳
  • application/json 序列化JSON數據
  • text/xml XML數據

這些body類型須要在http header頭部就寫上,可是okhttp不須要咱們手動在header寫上類型了.okhttp提供了FormBody和MultipartBody的類型,方便你的快速建立 application/x-www-form-urlencoded 與 multipart/form-data

FormBody 建立方式

/**
     * 此body是 默認application/x-www-form-urlencoded,你能夠進入FormBody類查看,第一行靜態常量就是這個
     */
   public void FormBody(){
       FormBody.Builder builder = new FormBody.Builder();
       builder.add("key","content");
       builder.build();
   }

MultipartBody 建立方式

 

/**
     * multipart/form-data
     */
   public void MultipartBody(){
       RequestBody requestBody = new RequestBody() {
           @Override
           public MediaType contentType() {
               return null;
           }

           @Override
           public void writeTo(BufferedSink sink) throws IOException {
               //上傳流 sink.write()


           }
       };
       MultipartBody.Builder builder = new MultipartBody.Builder();
       builder.addFormDataPart("key","content");//表單數據
       builder.addFormDataPart("file_key","/path/image.jpg",requestBody);//文件數據
       MultipartBody multipartBody = builder.build();
   }

手動建立4種body

固然,有特殊需求你還能夠添加手動其餘body類型,create也支持好幾種數據的上傳形式

 /**
     * 手動建立4種body
     */
   public void RequestBody(){
       RequestBody applicationFormUrlencodedBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"),new String("demo").getBytes());
       RequestBody multipartBody = RequestBody.create(MediaType.parse("multipart/form-data; charset=utf-8"),new File("/path/image.jpg"));
       RequestBody jsonBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),"content");
       RequestBody textbody = RequestBody.create(MediaType.parse("text/xml; charset=utf-8"),"content");

   }

 


 

實現OkHttpClient客戶端單例模式

public class OkHttpClientCreate {
    private static final boolean IS_RETRY = false;//失敗是否重連
    private static final int CONNECT_TIME = 10;//設置鏈接超時時間 單位:秒
    private static final int READ_TIME = 10;//設置讀取超時時間
    private static final int WRITE_TIME = 10;//設置寫入超時間
    private static OkHttpClient mOkHttpClient;
    public static OkHttpClient CreateClient(){
        if (mOkHttpClient == null){
            return mOkHttpClient = new OkHttpClient.Builder()
                    .retryOnConnectionFailure(IS_RETRY)
                    .connectTimeout(CONNECT_TIME,TimeUnit.SECONDS)//鏈接超時
                    .readTimeout(READ_TIME,TimeUnit.SECONDS)//讀取超時
                    .writeTimeout(WRITE_TIME,TimeUnit.SECONDS)//寫入超時
//                    .callTimeout()//呼叫超時,設置此參數爲總體流程請求的超時時間
//                    .addInterceptor() //設置攔截器
//                    .authenticator() //設置認證器
//                    .proxy()//設置代理
                    .build();
        }
        return mOkHttpClient;
    }

    public static void destroy(){
        mOkHttpClient = null;
    }
    
}
相關文章
相關標籤/搜索