Retrofit2+okHttp3使用總結(jié)

使用前準(zhǔn)備


Build.gradle文件配置

  • dependencies配置
    compile 'com.squareup.retrofit2:retrofit:2.0.0'
    compile 'com.squareup.retrofit2:converter-gson:2.0.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'

網(wǎng)絡(luò)框架搭建


  • 服務(wù)創(chuàng)建類封裝(HTTP)
public class ServiceGenerator {
    public static final String API_BASE_URL = "";
    public static int READ_TIMEOUT = 60;
    public static int WRIT_TIMEOUT = 60;
    public static int CONNECT_TIMEOUT = 60;
    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
            .readTimeout(READ_TIMEOUT,TimeUnit.SECONDS)//設(shè)置讀取超時(shí)時(shí)間
            .writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//設(shè)置寫的超時(shí)時(shí)間
            .connectTimeout(CONNECT_TIMEOUT,TimeUnit.SECONDS);

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)                 .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass) {
        return createService(serviceClass, null);
    }

    public static <S> S createService(Class<S> serviceClass, final String authToken) {
        if (authToken != null) {
            httpClient.addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Interceptor.Chain chain) throws IOException {
                    Request original = chain.request();

                    // Request customization: add request headers
                    Request.Builder requestBuilder = original.newBuilder()
                            .method(original.method(), original.body());

                    Request request = requestBuilder.build();
                    return chain.proceed(request);
                }
            });
        }

        OkHttpClient client = httpClient
                // 日志攔截器
                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .build();
        Retrofit retrofit = builder.client(client).build();
        return retrofit.create(serviceClass);
    }
}

使用說(shuō)明:
API_BASE_URL 用來(lái)配置api主地址
READ_TIMEOUT 用來(lái)配置讀取超時(shí)時(shí)間
WRIT_TIMEOUT 用來(lái)配置寫超時(shí)時(shí)間
CONNECT_TIMEOUT 用來(lái)配置連接超時(shí)時(shí)間
addConverterFactory() 用來(lái)設(shè)置解析器,此處我們?cè)O(shè)置的是gson的解析
addInterceptor() 用來(lái)設(shè)置日志攔截器

  • 服務(wù)創(chuàng)建類封裝(HTTPS)
 public class HttpsServiceGenerator {
    public static final String API_BASE_URL = "";
    public static int READ_TIMEOUT = 250;
    public static int WRIT_TIMEOUT = 250;
    public static int CONNECT_TIMEOUT = 250;
    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)                   .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass) {
        return createService(serviceClass, null);
    }

    public static <S> S createService(Class<S> serviceClass, final String authToken) {
        if (authToken != null) {
            httpClient.addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Interceptor.Chain chain) throws IOException {
                    Request original = chain.request();

                    // Request customization: add request headers
                    Request.Builder requestBuilder = original.newBuilder()
                            .method(original.method(), original.body());

                    Request request = requestBuilder.build();
                    return chain.proceed(request);
                }
            });
        }
        Retrofit retrofit = builder.client(getUnsafeOkHttpClient()).build();
        return retrofit.create(serviceClass);
    }

    private static OkHttpClient getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            X509Certificate[] x509Certificates = new X509Certificate[0];
                            return x509Certificates;
                        }
                    }
            };

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient okHttpClient =
                    new OkHttpClient.Builder()
                            .readTimeout(READ_TIMEOUT,TimeUnit.SECONDS)//設(shè)置讀取超時(shí)時(shí)間
                            .writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//設(shè)置寫的超時(shí)時(shí)間
                            .connectTimeout(CONNECT_TIMEOUT,TimeUnit.SECONDS)
                            .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                            .sslSocketFactory(sslSocketFactory)
                            .hostnameVerifier(new HostnameVerifier() {
                                @Override
                                public boolean verify(String hostname, SSLSession session) {
                                    return true;
                                }
                            }).build();

            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

使用說(shuō)明:
可以看出https 和http的服務(wù)類主要區(qū)別在于retrofit對(duì)象的構(gòu)造方法不同哈踱。
主要就是sslSocketFactory()方法蚓哩。是用來(lái)添加sslsocketFactory的者祖,也就是客戶端發(fā)送的請(qǐng)求都等于手持了這樣的證書(shū),這樣就可以和服務(wù)器交互了悦施。
SslsocketFactory對(duì)象的獲取方法如下:

final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
  • 請(qǐng)求體和響應(yīng)體封裝
 {
    "page":2,
    "pageSize":10
}

Json體類似如上所示的可以封裝為如下的請(qǐng)求體/響應(yīng)體,此處可以借用GsonFormat插件,輸入json體就可以快速生產(chǎn)請(qǐng)求體/響應(yīng)體bean類郭赐。

public class GetTradeDetailRequest {


    /**
     * page : 2
     * pageSize : 10
     */

    private int page;
    private int pageSize;

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
}
  • 服務(wù)接口封裝
public interface BalanceService {
    @GET("balance")
    Call<GetBalanceResponse> getBalance(@Header("AccessToken") String accessToken);

    @POST("balance/detail")
    Call<GetTradeDetailResponse> getDetail(@Header("AccessToken") String accessToken , @Body GetTradeDetailRequest tradeDetailRequest);
}
 

使用說(shuō)明:
此接口用來(lái)聲明請(qǐng)求類型,call聲明的類型是返回體的bean類,@header是請(qǐng)求的頭确沸,@body是返回體的類型捌锭。

  • 請(qǐng)求model封裝
public class BalanceModel {
    private static BalanceModel balanceModel;
    private BalanceService mBalanceService;

    /**
     * Singleton
     */
    public static BalanceModel getInstance(Context context) {
        if (balanceModel == null) {
            balanceModel = new BalanceModel(context);
        }
        return balanceModel;
    }

    public BalanceModel(Context context) {
        mBalanceService =  HttpsServiceGenerator.createService(BalanceService.class);
    }

    public Call<GetBalanceResponse> getBalanceResponseCall(String accessToken) {
        Call<GetBalanceResponse> balanceResponseCall = mBalanceService.getBalance(accessToken);
        return balanceResponseCall;
    }
}

使用說(shuō)明:
此接口用來(lái)聲明請(qǐng)求model的俘陷,主要用到的是上面的服務(wù)接口。 此類主要用來(lái)獲取網(wǎng)絡(luò)請(qǐng)求體的观谦。

  • 響應(yīng)事件回調(diào)類封裝
public abstract class Callback<T extends Object> implements retrofit2.Callback<T> {

    @Override
    public void onResponse(Call<T> call, Response<T> response) {
        if (response.raw().code() == 200){
            Log.i("internet response","200");
            onSuccess(response);
        }else if (response.raw().code() == 404){
            Log.i("internet response","404");
            onNotFound();
        }
    }

    @Override
    public void onFailure(Call<T> call, Throwable t) {

    }


    public abstract void onSuccess(Response<T> response);

    public void onNotFound(){
        return;
    }
}

使用說(shuō)明:
通常在發(fā)送網(wǎng)絡(luò)請(qǐng)求的時(shí)候只有兩種結(jié)果拉盾,一是請(qǐng)求發(fā)送失敗,二是服務(wù)器接收到了請(qǐng)求并且響應(yīng)了豁状。
onFailure()主要用來(lái)處理請(qǐng)求發(fā)送失敗的情況捉偏,onResponse()用來(lái)處理服務(wù)器的響應(yīng)內(nèi)容。
response.raw().code()的值就是我們?cè)诰W(wǎng)站開(kāi)發(fā)中遇到的標(biāo)識(shí)代碼泻红,200代表成功返回消息體夭禽,404代表api路徑?jīng)]找到(api路徑配置出錯(cuò)是會(huì)導(dǎo)致這樣的情況,當(dāng)然也可能是服務(wù)器的環(huán)境出了問(wèn)題承桥,導(dǎo)致手機(jī)訪問(wèn)不到)驻粟,500代表的是服務(wù)器內(nèi)部錯(cuò)誤(請(qǐng)求中的參數(shù)配置有誤會(huì)導(dǎo)致這樣的情況)。

  • 代碼中使用:
private void httpLoginRequest(String phone, String password) {
        mPushToken = mPushAgent.getRegistrationId();
        GetLoginRequest loginRequest = new GetLoginRequest();
        loginRequest.setPhone(phone);
        loginRequest.setPassword(password);
        loginRequest.setPushtoken(mPushToken);
        loginRequest.setCarrier(mCarrier);
        final Call<GetLoginResponse> callLogin = loginModel.getLoginResponseCall(loginRequest);
        callLogin.enqueue(new Callback<GetLoginResponse>() {
            @Override
            public void onFailure(Call<GetLoginResponse> calllist, Throwable t) {
                ToastUtils.showToast(LoginActivity.this,"網(wǎng)絡(luò)服務(wù)異常");
                materialDialog.dismiss();
                callLogin.cancel();
            }

            @Override
            public void onSuccess(Response<GetLoginResponse> response) {
                GetLoginResponse loginResponse = response.body();
                userBean = loginResponse.getData();
                if (loginResponse.getErrcode() == 0) {
                    ToastUtils.showToast(LoginActivity.this,"登錄成功");
                    ActivityCollector.finishAll();
                    startActivity(new Intent(LoginActivity.this, MapActivity.class));
                    AppConfigUtils.getInstanse(LoginActivity.this).clearAll();
                    AppConfigUtils.getInstanse(LoginActivity.this).setUserBean(userBean);
                    materialDialog.dismiss();
                } else if (loginResponse.getErrcode() == 203) {
                    ToastUtils.showToast(LoginActivity.this,"用戶名或密碼錯(cuò)誤");
                    materialDialog.dismiss();
                }else if (loginResponse.getErrcode() == 999){
                    materialDialog.dismiss();
                    ToastUtils.showToast(LoginActivity.this,"服務(wù)器異常凶异,請(qǐng)稍后再試");
                }
                callLogin.cancel();
            }

            @Override
            public void onNotFound() {
                materialDialog.dismiss();
                ToastUtils.showToast(LoginActivity.this,"404");
                super.onNotFound();
                callLogin.cancel();
            }
        });
    }
private void httpBalanceRequest(String accessToken) {
        BalanceModel balanceModel = BalanceModel.getInstance(getApplicationContext());
        final Call<GetBalanceResponse> balanceResponseCall = balanceModel.getBalanceResponseCall(accessToken);
        balanceResponseCall.enqueue(new Callback<GetBalanceResponse>() {
            @Override
            public void onResponse(Call<GetBalanceResponse> calllist, Response<GetBalanceResponse> response) {
                GetBalanceResponse balanceResponse = response.body();
                if (balanceResponse.getErrcode() == 0) {
                    mMoneyTV.setText(balanceResponse.getData().getBalance());
                } else if (balanceResponse.getErrcode() == 999) {
                    ToastUtils.showToast(BalanceActivity.this,"服務(wù)器異常蜀撑,請(qǐng)稍后再試");
                    mMoneyTV.setText("0.00");
                } else if (balanceResponse.getErrcode() == 403) {
                    ToastUtils.showToast(BalanceActivity.this,"登錄已失效,請(qǐng)重新登錄");
                    AppConfigUtils.getInstanse(BalanceActivity.this).clearAll();
                    ActivityCollector.finishAll();
                    LoginActivity.actionStart(BalanceActivity.this,mPhone,"");
                }
                balanceResponseCall.cancel();
            }

            @Override
            public void onFailure(Call<GetBalanceResponse> calllist, Throwable t) {
                ToastUtils.showToast(BalanceActivity.this,"網(wǎng)絡(luò)服務(wù)異常");
                balanceResponseCall.cancel();
            }
        });
    }

使用說(shuō)明:
這段代碼使用的是自己封裝的響應(yīng)事件回調(diào)類剩彬,當(dāng)然也可以用第二張圖retrofit默認(rèn)的那套酷麦,用自己封裝的有個(gè)好處就是404not found 可以處理進(jìn)行操作,如果用默認(rèn)的那套喉恋,在404的時(shí)候這段代碼就會(huì)崩潰沃饶。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轻黑,隨后出現(xiàn)的幾起案子糊肤,更是在濱河造成了極大的恐慌,老刑警劉巖氓鄙,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馆揉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡抖拦,警方通過(guò)查閱死者的電腦和手機(jī)升酣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)态罪,“玉大人噩茄,你說(shuō)我怎么就攤上這事「淳保” “怎么了绩聘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我君纫,道長(zhǎng)驯遇,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任蓄髓,我火速辦了婚禮叉庐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘会喝。我一直安慰自己陡叠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布肢执。 她就那樣靜靜地躺著枉阵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪预茄。 梳的紋絲不亂的頭發(fā)上兴溜,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音耻陕,去河邊找鬼拙徽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诗宣,可吹牛的內(nèi)容都是我干的膘怕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼召庞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼岛心!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起篮灼,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤忘古,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后诅诱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體髓堪,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年逢艘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骤菠。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡它改,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出商乎,到底是詐尸還是另有隱情央拖,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站鲜戒,受9級(jí)特大地震影響专控,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜遏餐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一伦腐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧失都,春花似錦柏蘑、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至庞溜,卻和暖如春革半,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背流码。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工又官, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人旅掂。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓赏胚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親商虐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子觉阅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)秘车,斷路器典勇,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評(píng)論 25 707
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法叮趴,內(nèi)部類的語(yǔ)法割笙,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法眯亦,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,581評(píng)論 18 399
  • 參考Android網(wǎng)絡(luò)請(qǐng)求心路歷程Android Http接地氣網(wǎng)絡(luò)請(qǐng)求(HttpURLConnection) 一...
    合肥黑閱讀 21,234評(píng)論 7 63
  • 學(xué)穿衣服鞋子 伊一歲多時(shí)伤溉,對(duì)自己穿鞋充滿了極大的興趣。我們的態(tài)度是鼓勵(lì)與表?yè)P(yáng)妻率,常常對(duì)她說(shuō)乱顾,“寶寶好棒啊,居然能自己...
    明媚Sopy閱讀 157評(píng)論 4 5