Retrofit 2.0 配置篇

獲取實例

獲取 OkHttpClient.Builder 對象:

OkHttpClient.Builder builder = new OkHttpClient.Builder();

Log信息攔截器

Debug模式查看網(wǎng)絡請求、打印Log信息申鱼,發(fā)布時不需要Log

添加依賴

項目的build.gradle添加:

compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'

設置攔截器

if(BuildConfig.DEBUG){
    //Log信息攔截器
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
    loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    //設置Log
    builder.addInterceptor(loggingInterceptor);
}

緩存機制

無網(wǎng)絡時柴灯,也能顯示數(shù)據(jù)。

File cacheFile = new File(MyApplication.getContext().getExternalCacheDir(), "DemoCache");
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
Interceptor cacheInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!AppUtils.networkIsAvailable(MyApplication.getContext())) {
            request = request.newBuilder()
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build();
        }
        Response response = chain.proceed(request);
        if (AppUtils.networkIsAvailable(MyApplication.getContext())) {
            int maxAge = 0;
            // 有網(wǎng)絡時 設置緩存超時時間0個小時
            response.newBuilder()
                    .header("Cache-Control", "public, max-age=" + maxAge)
                    .removeHeader("Demo")// 清除頭信息捞魁,因為服務器如果不支持,會返回一些干擾信息离咐,不清除下面無法生效
                    .build();
        } else {
            // 無網(wǎng)絡時谱俭,設置超時為4周
            int maxStale = 60 * 60 * 24 * 28;
                response.newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                    .removeHeader("nyn")
                    .build();
        }
        return response;
    }
};
builder.cache(cache).addInterceptor(cacheInterceptor);

公共參數(shù)

Interceptor addQueryParameterInterceptor = new Interceptor(){
    @Override
    public Response intercept(Chain chain) throws IOException{
        Request originalRequest = chain.request();
        Request request;
        String method = originalRequest.method();
        Headers headers = originalRequest.headers();
        HttpUrl modifiedUrl = originalRequest.url().newBuilder()
                // Provide your custom parameter here
                .addQueryParameter("platform", "android")
                .addQueryParameter("version", "1.0.0")              
                .build();
        request = originalRequest.newBuilder().url(modifiedUrl).build();
        return chain.proceed(request);
    }
};
builder.addInterceptor(addQueryParameterInterceptor);

請求頭

以下為初始配置方式添加請求頭,另一種為定義接口方式宵蛀,詳見注解篇 @Headers昆著。

Interceptor headerInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        Request.Builder requestBuilder = originalRequest.newBuilder()
                .header("AppType", "TPOS")
                .header("Content-Type", "application/json")
                .header("Accept", "application/json")
                .method(originalRequest.method(), originalRequest.body());
        Request request = requestBuilder.build();
        return chain.proceed(request);
    }
};
builder.addInterceptor(headerInterceptor );

cookie

服務端可能需要保持請求是同一個 cookie ,看需求术陶。

添加依賴

項目的build.gradle添加:

compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'

設置cookie

CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
builder.cookieJar(new JavaNetCookieJar(cookieManager));

超時凑懂、重連

//設置超時時間
builder.connectTimeout(15, TimeUnit.SECONDS); 
builder.readTimeout(20, TimeUnit.SECONDS);
builder.writeTimeout(20, TimeUnit.SECONDS);
//錯誤重連
builder.retryOnConnectionFailure(true);

設置Retrofit

OkHttpClient okHttpClient = builder.build();
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(ApiStores.API_SERVER_URL)
        //設置 Json 轉(zhuǎn)換器
        .addConverterFactory(GsonConverterFactory.create())
        //RxJava 適配器
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .client(okHttpClient)
        .build();

Json轉(zhuǎn)換器

默認情況,Retrofit 只能反序列化 Http bodiesOkHttpResponseBody 且只能接受它為 @Body 的類型梧宫。

Retrofit 2.0 支持多種解析方式來解析響應數(shù)據(jù):

  • Gson::com.squareup.retrofit2:converter-gson
  • Jacksoncom.squareup.retrofit2:converter-jackson
  • Moshicom.squareup.retrofit2:converter-moshi
  • Protobufcom.squareup.retrofit2:converter-protobuf
  • Wirecom.squareup.retrofit2:converter-wire
  • Simple XMLcom.squareup.retrofit2:converter-simplexml
  • Scalars (primitives, boxed, and String):com.squareup.retrofit2:converter-scalars

自定義轉(zhuǎn)換器
繼承Converter.Factory class
http://simple.sourceforge.net/

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.nuuneoi.com/base/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

RxJava

除了提供 Callback 形式的API接谨,還有RxJava版本的 Observable 形式API

添加依賴

compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta3'
compile 'io.reactivex:rxandroid:1.0.1'

設置

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.nuuneoi.com/base/")
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

栗子一:獲取一個User對象的接口

Callback 方式:

//定義請求
@GET("/user")
public void getUser(@Query("userId") String userId, Callback<User> callback);

//使用
getUser(userId, new Callback<User>() {
    @Override
    public void success(User user) {
        userView.setUser(user);
    }

    @Override
    public void failure(RetrofitError error) {
        // Error handling
        ...
    }
};

Rxjava 方式:

//定義請求
@GET("/user")
public Observable<User> getUser(@Query("userId") String userId);

//使用
getUser(userId)
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<User>() {
            @Override
            public void onNext(User user) {
                userView.setUser(user);
            }

            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable error) {
                // Error handling
                ...
            }
        });

栗子二:獲取到的 User 不直接顯示塘匣,先與數(shù)據(jù)庫中的數(shù)據(jù)比對修正后再顯示

Callback 方式:

getUser(userId, new Callback<User>() {
    @Override
    public void success(User user) {
        processUser(user); // 嘗試修正 User 數(shù)據(jù)
        userView.setUser(user);
    }

    @Override
    public void failure(RetrofitError error) {
        // Error handling
        ...
    }
};

注意:數(shù)據(jù)庫操作屬耗時操作脓豪,所以要避免在主線程中操作數(shù)據(jù)庫。

//修改后
getUser(userId, new Callback<User>() {
    @Override
    public void success(User user) {
        new Thread() {
            @Override
            public void run() {
                processUser(user); // 嘗試修正 User 數(shù)據(jù)
                runOnUiThread(new Runnable() { // 切回 UI 線程
                    @Override
                    public void run() {
                        userView.setUser(user);
                    }
                });
            }
        }).start();
    }

    @Override
    public void failure(RetrofitError error) {
        // Error handling
        ...
    }
};

Rxjava 方式:

getUser(userId)
        .doOnNext(new Action1<User>() {
            @Override
            public void call(User user) {
                processUser(user);
            })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<User>() {
            @Override
            public void onNext(User user) {
                userView.setUser(user);
            }

            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable error) {
                // Error handling
                ...
            }
        });

栗子三:/user 接口不能直接訪問忌卤,需要填入在線獲取的 token

Callback 方式:可以嵌套Callback

@GET("/token")
public void getToken(Callback<String> callback);

@GET("/user")
public void getUser(@Query("token") String token, @Query("userId") String userId, Callback<User> callback);

...

getToken(new Callback<String>() {
    @Override
    public void success(String token) {
        getUser(token, userId, new Callback<User>() {
            @Override
            public void success(User user) {
                userView.setUser(user);
            }

            @Override
            public void failure(RetrofitError error) {
                // Error handling
                ...
            }
        };
    }

    @Override
    public void failure(RetrofitError error) {
    // Error handling
        ...
    }
});

Rxjava 方式:

@GET("/token")
public Observable<String> getToken();
    
@GET("/user")
public Observable<User> getUser(@Query("token") String token, @Query("userId") String userId);
    
...
    
getToken()
        .flatMap(new Func1<String, Observable<User>>() {
            @Override
            public Observable<User> onNext(String token) {
                return getUser(token, userId);
            })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<User>() {
            @Override
            public void onNext(User user) {
                userView.setUser(user);
            }
    
            @Override
            public void onCompleted() {
            }
    
            @Override
            public void onError(Throwable error) {
                // Error handling
                ...
            }
        });

完整配置

public class AppClient {
    public static Retrofit retrofit = null;

    public static Retrofit retrofit() {
        if (retrofit == null) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        /**
        *   設置緩存
        */

        /**
        *  公共參數(shù)
        */

        /**
        * 設置頭
        */           
    
        /**
        * Log信息攔截器
        */
    
        /**
        * 設置cookie
        */
    
        /**
        * 設置超時和重連
        */
    
        //以上設置完成
        OkHttpClient okHttpClient = builder.build();
    
        retrofit = new Retrofit.Builder()
                .baseUrl(ApiStores.API_SERVER_URL)
                //設置 Json 轉(zhuǎn)換器
                .addConverterFactory(GsonConverterFactory.create())
                //RxJava 適配器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .client(okHttpClient)
                .build();
        }
        return retrofit;
    }
}

混淆配置

# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on RoboVM on iOS. Will not be used at runtime.
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扫夜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子埠巨,更是在濱河造成了極大的恐慌,老刑警劉巖现拒,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辣垒,死亡現(xiàn)場離奇詭異,居然都是意外死亡印蔬,警方通過查閱死者的電腦和手機勋桶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侥猬,“玉大人例驹,你說我怎么就攤上這事⊥诉耄” “怎么了鹃锈?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瞧预。 經(jīng)常有香客問我屎债,道長仅政,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任盆驹,我火速辦了婚禮圆丹,結果婚禮上,老公的妹妹穿的比我還像新娘躯喇。我一直安慰自己辫封,他們只是感情好,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布廉丽。 她就那樣靜靜地躺著倦微,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雅倒。 梳的紋絲不亂的頭發(fā)上璃诀,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機與錄音蔑匣,去河邊找鬼劣欢。 笑死,一個胖子當著我的面吹牛裁良,可吹牛的內(nèi)容都是我干的凿将。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼价脾,長吁一口氣:“原來是場噩夢啊……” “哼牧抵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起侨把,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤犀变,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后秋柄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體获枝,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年骇笔,在試婚紗的時候發(fā)現(xiàn)自己被綠了省店。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡笨触,死狀恐怖懦傍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芦劣,我是刑警寧澤粗俱,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站虚吟,受9級特大地震影響源梭,放射性物質(zhì)發(fā)生泄漏娱俺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一废麻、第九天 我趴在偏房一處隱蔽的房頂上張望荠卷。 院中可真熱鬧,春花似錦烛愧、人聲如沸油宜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慎冤。三九已至,卻和暖如春沧卢,著一層夾襖步出監(jiān)牢的瞬間蚁堤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工但狭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留披诗,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓立磁,卻偏偏與公主長得像呈队,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子唱歧,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容