1. 程式人生 > >升級okhttp3.0+和retrofit2.0+的過程以及遇到的坑

升級okhttp3.0+和retrofit2.0+的過程以及遇到的坑

包名變化

okhttp3.0之前是:com.squareup.okhttp.*,

而到3.0之後變成:okhttp3.*

retrofit2.0之前:retrofit.*

retrofit2.0之後:retrofit2.*

都在末尾增加了版本號,顯示的更專業,但是這也給我們升級帶來了麻煩。

首先看一下retrofit1.9+okhttp2.2的配置程式碼

public class MainRetrofit {

    final MeoHttp mService;
    final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").serializeNulls().create();
    RequestInterceptor requestInterceptor = new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            request.addHeader("User-Agent", AppConstants.USER_AGENT);
            request.addHeader("X-Requested-With", "XMLHttpRequest");
            request.addHeader("Cookie", AppConstants.PHPSESSID);

        }
    };
    MainRetrofit() {
        OkHttpClient client = new OkHttpClient();
        client.setReadTimeout(41, TimeUnit.SECONDS);
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setClient(new OkClient(client))
                .setEndpoint(MainFactory.HOST)
                .setConverter(new GsonConverter(gson))
                .setLogLevel(RestAdapter.LogLevel.NONE)
                .setRequestInterceptor(requestInterceptor)
                .build();
        mService = restAdapter.create(MeoHttp.class);
   
    }

    public MeoHttp getService(){
        return mService;
    }

}
okhttp3.0以及retrofit2.0均採用了builder構建者模式配置
 final RequestApi api;
    final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").serializeNulls().create();
    Interceptor requestInterceptor;
    private static final okhttp3.OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    public MainRetrofit(final boolean hasCookie) {
        httpClient.readTimeout(60, TimeUnit.SECONDS).
                connectTimeout(2, TimeUnit.SECONDS).build();
        requestInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                String cookie = "";
                if (hasCookie) {
                    cookie = AppConfig.Net.COOKIE_HEAD + CookieManager.getCookie();
                }
                Request compressedRequest = request.newBuilder()
                        .header("Cookie", cookie)
                        .header("Accept-Language", Locale.getDefault().toString())
                        .header("Accept-Charset", "utf-8")
                        .header("Connection", "Keep-Alive")
                        .header("User-Agent", getUserAgent())
                        .build();
                Response response = chain.proceed(compressedRequest);
                return response;
            }
        };
        httpClient.interceptors().add(requestInterceptor);
        OkHttpClient okHttpClient = httpClient.build();
        Retrofit client = new Retrofit.Builder()
                .baseUrl(AppConfig.Net.HOST)
                .addConverterFactory(new ScalarsConverterFactory())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .client(okHttpClient)
                .build();
        //retrofit 沒有日誌列印功能
        /*if (AppConfig.IS_DEVELOPING) {
            //日誌可用
            client.setLogLevel(RestAdapter.LogLevel.FULL);
        } else {
            client.setLogLevel(RestAdapter.LogLevel.NONE);
        }*/
        api = client.create(RequestApi.class);
而且retrofit2.0沒有列印日誌的功能,所以只能在okhttp的攔截器裡列印日誌

retrofit1.9的介面呼叫方式:

GET:

/**
 * 獲得使用者地址
 */
@GET("/user/Address?")
void getAddress(Callback<AddressInfo>callback);

POST:
/**
 * 上傳畫作
 * @param content 圖集描述
 * @param atk token值
 * @param file 檔案
 */
@Multipart
@POST("/user/uploadPicture?")
void upLoadPaint
(@Part("content")String content, @Part("t")String atk, @Part("upfile") TypedFile file, Callback<BaseResponse> callback);
而對應2.0之後的方式是這樣的

GET:

/**
 * 獲得使用者地址
 */
@GET("/user/Address?")
Calll<AddressInfo> getAddress();
POST:
/**
 * 上傳畫作
 * @param content 圖集描述
 * @param atk token值
 * @param file 檔案
 */
@Multipart
@POST("/user/uploadPicture?")
Call<BaseResponse> upLoadPaint(@Part("content")String content, @Part("t")String atk,
@Part("upfile") RequestBody body); 大致的升級過程算是完成了

接下來講講有什麼坑:

1.純粹使用retrofit介面返回不能是void ,而是相對應了Call<T>,介面的實現不在是直接使用Call回撥,而是用getAddress().enqueue(new CallBack)

  這裡面的變動有點大,如果沒做好回撥函式的封裝,那升級的工作量就有點大了,這樣返回一個call可以用於取消請求。

2.在Retrofit 1.9中,如果獲取的 response 不能背解析成定義好的物件,則會呼叫failure。但是在Retrofit 2.0中,不管 response 是否能被解析。onResponse總是會被呼叫。但是在結果不能被解析的情況下,response.body()會返回null。別忘了處理這種情況。

如果response存在什麼問題,比如404什麼的,onResponse也會被呼叫。你可以從response.errorBody().string()中獲取錯誤資訊的主體。

3.retrofit2.0去掉了一些類:RetrofitError,TypeFile MultipartTypedOutput,如果在1.9中用到,升級的時候需要注意 [email protected]註解在1.9的時候使用方式:
@Path(value="url", encode=false) String url

2.0時會導致encoded失效,此時推薦使用@Url動態替換url地址

@Multipart
@POST
Call<String>  upload(@Url String url,
@PartMap Map<String, RequestBody> params);
5.多圖片上次的坑:MultipartTypedOutput,以及TypeFile在2.0之後被去除了

1.9的多圖片上傳方式:

/** * @param multipartTypedOutput 多個引數載入
 */
@POST("/user/applyPainting?")
void request2BePaint(@Body MultipartTypedOutput multipartTypedOutput,Callback<BaseResponse> callback);
multipartTypedOutput組裝:
MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
multipartTypedOutput.addPart("t",new TypedString(painter.atk));
multipartTypedOutput.addPart("content",new TypedString(painter.content));for (int i=0;i<painter.fileImages.length;i++){
   multipartTypedOutput.addPart("upfile["+i+"]",new TypedFile("image/jpeg", new File(painter.fileImages[i])));
}
相對於簡單些,而到2.0之後就感覺很繁瑣
/**
 * 上傳檔案*/
@Multipart
@POST
Call<String>  upload(@Url String url,
@PartMap Map<String, RequestBody> params);
組裝map以及RequestBody
RequestBody requestFile = null;
Map<String, RequestBody>  photos = new HashMap<>();for (int i = 0; i < formFiles.size(); i++) {
    
    //生成臨時壓縮圖片檔案
final File tempFile = FileUtils.createFile(AppConfig.MAIN_DIR_IMG,
"IMG_TEMP_" + System.currentTimeMillis() + ".jpg");
Bitmap bitmap = PhotoUtils.compressBitmap(formFiles.get(i).getFile().getPath());
FileOutputStream fos = new FileOutputStream(tempFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, fos);
requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), tempFile);
photos.put("AttachmentKey"+i+"\"; filename=\""+keys.get(i),requestFile);}
以上就是我升級的過程,如有問題和錯誤請留言

相關推薦

升級okhttp3.0+retrofit2.0+的過程以及遇到的

包名變化 okhttp3.0之前是:com.squareup.okhttp.*, 而到3.0之後變成:okhttp3.* retrofit2.0之前:retrofit.* retrofit2.0之後:retrofit2.* 都在末尾增加了版本號,顯示的更專業,但是這也給

Retrofit2.0RxJava2.0的簡單封裝

一、首先新增專案依賴: implementation "com.squareup.okhttp3:logging-interceptor:$var.loggingInterceptor"

升級到Xcode8ios10.0的時候呼叫相機崩潰

所以需要增加相簿:Privacy - Photo Library Usage Description允許此許可權才能儲存圖片 要錄製視訊的一定要加上(麥克風:Privacy - Microphone Usage Description)不然會崩的麥克風:Privacy - Microphone Usag

vue2.0vue1.0路由對比以及腳手架初始路由分析

2.0新版本路由相比1.0在使用上做了一些改動,但核心思想並未改變,接下來稍作分析和對比,使用路由之前都需要引入vue-router.js檔案 一、兩個路由版本的初步分析 1.0 .js /*1.建立根元件 必須得要有一個根元件*/

Android6.07.0上遇到的以及解決方法

android系統的版本已經更新到了8.0了。根據統計版本的分佈已經從過去的2.x推進到4.x以上了。所以開發中已經幾乎可以不考慮2.x等版本了。 然後像6.0以上的份額也越來越多。所以開發中是有必要考慮6.0以上版本的。 現在比較新的版本中,6.0(API

django1.0django2.0的基於正則表達式的url區別

正則 url django1.0 django2.0django1.0和django2.0的基於正則表達式的url區別

hdfs1.02.0復習

sla 系統配置 一致性 slaves 負責 們的 -m 檢測 hadoop2.0 1、Namenode元數據兩種映射:(1)文件名 -> block數據塊的映射(2)block數據塊 -> datanode節點地址的映射細節:(1)是持久化到NN的磁盤的(fs

Shader-AlphaTest(1.02.0

所謂Alpha測試,就是指測試畫素點的a值,只有當該畫素點的a值符合要求時,才渲染該畫素,否則不渲染該畫素. 首先來看1.0版本: Shader "Custom/AlphaTest" { Properties { _MainTex ("Texture", 2D) = "white

VUE CLI 3.02.0的引入模組的一些改變

1.引入模組一定要加.vue 剛剛接觸vue cli 3.0 自己開發中引入模組遇到一些問題。 因為2.0中 引入模組的字尾可以不用.vue.字尾 在3.0中就會出現 下圖的 錯誤 提示你 未找到模組。     加了.vue字尾之後模組之後. 再次執行 npm run s

vue3.02.0的區別及專案的搭建

  3.0 新加入了 TypeScript 以及 PWA 的支援 部分命令發生了變化: 下載安裝  npm install -g [email protected] 刪除了vue list 建立專案&n

Android camera framework7.06.0 主要差異

目前差異主要體現在介面封裝和程序分離方面。 1.程式碼結構 1).android6.0程式碼   目前Android6.0的程式碼,本地沒有原始碼,這裡就拿伺服器上版本了。可以發現在Android6.0上,介面都是在native層以原始碼方式實現了。由於以I開頭的檔案都具有b

selenium 1.0、selenium2.0selenium3.0區別

selenium 1.0 RC幾個核心組成部分: RC Server - jar ,主要負責跟瀏覽器打交道 RC Client -jar,一系列jar包,主要用來寫測試用例 RC core -javascript ,由RC Server注入到瀏覽器的selenium 核心主要操作控制元件 這裡RC的

OpenCV中MatIplImage之間的相互裝換(OpenCV2.0OpenCV3.0

Mat是OpenCV和C++介面的矩陣類,IplImage是OpenCV和C語言介面的結構體。 Mat讀取顯示用的是imread、imshow等,IplImage讀取顯示用的是cvLoadImage()、cvShowImage()。 有時候會涉及到兩者之間的轉換,下面詳細見介紹一下兩者之

Android App相容8.09.0

Android在8.0限制了後臺服務這些,啟動後臺服務需要設定通知欄,使服務變成前臺服務。但是在9.0上,就會出現Permission Denial: startForeground requires android.permission.FOREGROUND_SERVICE。 解決辦法

android8.09.0適配的一些問題

1.懸浮窗windowmanager許可權問題 需要跳轉到對應的系統許可權管理處讓使用者自己勾選 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 進入設定系統應用

javaSE (三十四)File類遞迴練習(統計資料夾大小、拷貝資料夾、層級列印資料夾、斐波拉契數列、獲取1000階乘全部0尾部0數目、約瑟夫環)

1、統計資料夾大小: 思路: 套用之前已經做過的,鍵入一個路徑,若有效則封裝成File類 初始化計數器len, 若資料夾下是檔案,則記錄檔案.length() 若資料夾下是資料夾,遞迴 輸出len 注:遞迴也可以刪除資料夾,但是一定要先刪除裡

0.0.0.0 127.0.0.1

127.0.0.1:是個(特殊的)IP地址,往往被分配給了loopback或僅區域網可以訪問的介面local-only interface 這是一個偽照的,假的,網路介面卡,其只能於同主機host內通訊 常用於:讓一個可以支援網路的程式,僅僅響應於同主機host內的客戶端

使用lifecycle時,1.0.01.0.3問題解決方法

將appcompat版本號改為27.0.2就行 implementation 'com.android.support:appcompat-v7:26.1.0' 我lifecycle修改後如下

C指標(*++argv)[0]*++argv[0]的區別

*argv[]在linux系統中是輸入引數的集合,其中argv[0]指向呼叫的程式名稱,後面才是使用者輸入的引數; 那 ( *++argv)[0]和*++argv[0]表達的是什麼意思呢? 其實他們有自己特定的意義。 先對他們進行分析,根據結合性,[]的優先順序要大於*和++, *和++

Camera1.0Camear2.0的區別

1. Camera2是通過系統服務拿到CameraManager來管理camera裝置物件,camera的一次預覽、拍照都是向請求會話(CaptureSession.StateCallback,攝像頭開啟時由相機裝置的輸出surface組成)傳送一次請求(CaptureRequest.Builder)。需