OkHttp3-從零開始的詳細使用到簡單封裝

Github地址---MyOkhttpUtils

初衷

對于okhttp3出來以后,使用的都是網上封裝好的庫,為了更好地理解封裝的內容,對okhttp本身的熟悉,肯定學一下子了,網上okhttp的方法很多,但是網上okhttp3方面的東西并不多,很多都過時的方法,總結了一下,講了一下okhttp3的基本使用方法,在下邊要耐心才會 。
封裝了一下基本大家使用得到的功能,想用的話可以直接拿去用,想擴展的話也可以直接下載擴展,代碼比較少,不了解okhttp的可以下載學習一下,大神門口右走吧。
封裝邏輯和使用的好多方法找不到,借鑒了兩位大神的邏輯,相當于簡化版本吧,封裝的比較全面的可以參照
hongyangAndroid / okhttputils
jeasonlzy/okhttp-OkGo

本文中庫的簡單使用介紹

  • 在project中添加依賴

    allprojects {
      repositories {
          ...
          maven { url 'https://jitpack.io' }
      }
     }
    

在app中添加依賴

    dependencies {
        compile 'com.github.jlcclidong:MyOkhttpUtils:0.10'
    }
  • 在本項目中使用okhttp的方法步驟
    在application中初始化,此步驟必須,別忘記在清單文件中注冊application否則不能使用
    Ok.init(this)
    .connectTimeout(3000l, TimeUnit.MILLISECONDS)
    .readTimeout(3000l, TimeUnit.MILLISECONDS)
    .commonParams("haha","1") //添加公共參數
    .commonHeader("nihao","1") //添加公共頭
    .AppInterceptor("eason", new LogInterceptor()) //應用攔截器
    .NetWorkInterceptor("eason",new LogInterceptor()) //網絡攔截器 將重定向等的request response頁攔截打印
    .CookieJar(new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(App.this)))
    .build();

  • 請求 其中callback有三種類型 fail都會返回Exception,不管是本身網絡問題還是404等問題都會返回此回調,可以通過Exception類型進行自行處理

    • callback有三種類型
      • JsonCallback<T> 傳入類自動轉換成bean,但是并未處理超大Json文件OOM 可自行通過流的方式來處理解析
      • CallBack 返回String
      • FileCallBack(String dir, String filename) 其中傳入文件夾和文件名來保存 返回進度(0-100)
  • get
    Ok.get().url("http://lab.zuimeia.com/wallpaper/category/1/")
    .param("page_size", 1)
    .build()
    .call(new JsonCallBack<Bean>() { //傳入實體類
    @Override
    public void fail(Exception e) {

                 }
    
                 @Override
                 public void success(Bean bean) {
                     mTv.setText(bean.getData().getBase_url());
                 }
             });
    
  • post 支持鍵值對和文件表單上傳
    Ok.post().url("https://www.baidu.com")
    .param("test", 1)
    .file("test", new File(""))
    .build()
    .call(new CallBack() {
    @Override
    public void fail(Exception e) {

                 }
    
                 @Override
                 public void success(String response) {
                     mTv.setText(response);
                 }
             });
    
  • download 文件下載只做到最基本的下載,斷點續傳和暫停下載暫未做,后續會追加
    Ok.download().url("http://static.oschina.net/uploads/space/2015/0629/170157_rxDh_1767531.png")
    .build()
    .tag(MainActivity.this)
    .call(new FileCallBack(getCacheDir().getAbsolutePath(), "github.png") {
    @Override
    public void progress(int progress) {
    mTv.setText(progress + "");
    }

                @Override
                public void success(File file) {
                    mIV.setImageBitmap(BitmapFactory.decodeFile(file.getAbsolutePath()));
                }
    
                @Override
                public void fail(Exception e) {
    
                }
            });
    
  • 取消

     Ok.cancle(MainActivity.this);
    
  • 同時支持PostJson() 和 PostFile()兩種方法

  • 其中日志打印時使用了格式化JsonFormat工具類

  • 請求時自動添加了 Accept-Language 和 User-Agent

  • 簡單封裝沒有太多的代碼,可以自行下載擴展

okhttp本身的基本使用

  • 初始化一個全局的okhttpclient
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .connectTimeout(3000l, TimeUnit.MILLISECONDS)
    .readTimeout(3000l, TimeUnit.MILLISECONDS)
    .addInterceptor( new LogInterceptor())
    .cookieJar(...)
    .build();
    當然初始化的方法有很多這里只是列出常用的方法,okhttp建議全局使用同一個

  • 為了更好的理解get,post方法,我們可以寫一個interceptor來監聽request和response,實現這個類不可以出現問題否則是無法進行正常請求的
    可以在此處修改request和response的參數添加緩存設置等,可自行添加
    主要方法有這樣幾個,必須重寫的方法
    @Override
    public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    logForRequest(request);
    return logForResponse(response, time);
    }
    打印request沒有什么特別注意的地方

    private void logForRequest(Request request) {
      try {
          Log.e("============request start===============");
          Log.e("url:" + request.url());
          Log.e("method:" + request.method());
          if (request.headers() != null && request.headers().size() > 0)
              Log.e("headers:" + request.headers().toString());
          Log.e("============request end=================");
      } catch (Exception e) {
          Log.e("log request has something worng!!");
      }
      }
    

打印response時注意,如果添加了interceptor則不能直接調用response.body().string()方法,調用此方法會直接close掉這個response,在callback中得不到正確的結果會報異常,只能使用response.newbuilder() 方法來使用新創建的response調用,eg
private Response logForResponse(Response response, long time) {
try {
Log.e("============response start==============");
//response.body().string()只能調用一次 body()就會關掉
//每次使用前都clone一份使用保證原來的body沒有被關掉
Response copy = response.newBuilder().build();
Log.e("responseurl:" + copy.request().url());
Log.e("response code:" + copy.code());
Log.e("total time:" + time);
if (!TextUtils.isEmpty(copy.message()))
Log.e("message:" + copy.message());
if (copy.headers() != null && copy.headers().size() > 0)
Log.e("headers:" + copy.headers().toString());
Log.e("============response end================");
ResponseBody body = copy.body();
if (body != null) {
MediaType mediaType = body.contentType();
if (mediaType != null) {
Log.e("============response body===============");
Log.e("Content-type:" + mediaType.toString());
if (isText(mediaType)) {
String content = body.string();
Log.e(JsonFormat.formatJson(content));
Log.e("============response body===============");
return response.newBuilder().body(ResponseBody.create(mediaType, content)).build();
} else {
Log.e(" maybe response content too large too print , ignored!");
}
}
} else {
Log.e(" body is null , ignored!");
}
} catch (Exception e) {
Log.e("log response has something worng!!");
}
return response;
}
這樣每次調用http請求是就可以詳細監聽其中的內容了
全部具體內容詳見github代碼

  • okhttp請求就是構建一個request加入到okhttpclicent中就可以了
    這里實例只講okhttp的異步請求,當然同步只是將enqueue()方法替換成execute()
    注意這個回調的onFailure只是回調了本身請求的一些失敗回調,例如超時IOException....當成功返回之后需要在onResponse中判斷response.code()來判斷是否是200,404,500之類的統一處理
    • get
      Request request = new Request.Builder().get()
      .url("https://www.baidu.com")
      .header("test","fds")
      .build();
      okHttpClient.newCall(request).enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {

          }
      
          @Override
          public void onResponse(Call call, Response response) throws IOException {
      
          }
      });
      
  • post
    只需要替換request post中需要傳一個requestBody,不同的post請求,需要不同的請求體,當然只是方便我們不同的需求。
    基本的鍵值對上傳在下面貼出,使用FormBody即可創建
    鍵值對加上文件上傳則需要MultipartBody來創建
    而普通的上傳json,上傳文件可以直接調用RequestBody的靜態方法來創建
    Request request = new Request.Builder().post(new FormBody.Builder().add("sdf","Sdfa").build())
    .url("https://www.baidu.com")
    .header("test","fds")
    .build();
    其他方法詳見本庫中request中做的封裝,都包含入內了
  • https的影響,okhttps本身不添加任何代碼就可以支持okhttps中公認的證書,類似于百度之類的,當時像12306這種只能手動添加了,當然也可以默認信任所有證書,具體由于本人公司并不需要就沒寫,推薦[ Android Https相關完全解析 當OkHttp遇到Https]
  • cookie持久化網上有很多方法,本庫采用的是franmontiel / PersistentCookieJar
  • okhttp3取消請求
    這個是比較坑的網上傳統的okhttpclicent.cancle(tag)方法發現沒有了,只可以通過call.cancle來取消請求,后來發現是這樣子根據tag來取消請求的,當然如果請求已經開始回調無法結束,正在上傳或者下載時會產生IOException
    //隊列中的call
    for (Call call : getInstance().dispatcher().queuedCalls()) {
    if (object.equals(call.request().tag())) {
    call.cancel();
    }
    }
    //運行中的call
    for (Call call : getInstance().dispatcher().runningCalls()) {
    if (object.equals(call.request().tag())) {
    call.cancel();
    }
    }

最后

好像沒什么了 ,感覺有幫助的幫忙點個star,辣眼睛了的我也沒辦法

啦啦啦啦.gif
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,933評論 18 139
  • 適配器模式上一篇文章我們已經分析了Retrofit解析注解封裝進ServiceMethod的流程,讀者在這里要記住...
    andcoder閱讀 682評論 0 2
  • 這篇文章主要總結Android著名網絡框架-okhttp的基礎使用。 okhttp是什么 okhttp是Andro...
    磨礪營IT閱讀 754評論 0 1
  • 這篇文章主要講 Android 網絡請求時所使用到的各個請求庫的關系,以及 OkHttp3 的介紹。(如理解有誤,...
    小莊bb閱讀 1,226評論 0 4
  • 李笑來的書里講到一個“既勤奮又懶惰”的例子,說是他的學生寧愿把書里的英語作文范例全部背下來也不愿意自己思考。仔細想...
    龍姑姑閱讀 527評論 8 2