android 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è)置讀取超時時間
.writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//設(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);
}
}
使用說明:
API_BASE_URL 用來配置api主地址
READ_TIMEOUT 用來配置讀取超時時間
WRIT_TIMEOUT 用來配置寫超時時間
CONNECT_TIMEOUT 用來配置連接超時時間
addConverterFactory() 用來設(shè)置解析器,此處我們設(shè)置的是gson的解析
addInterceptor() 用來設(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è)置讀取超時時間
.writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//設(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);
}
}
}
使用說明:
可以看出https 和http的服務(wù)類主要區(qū)別在于retrofit對象的構(gòu)造方法不同。
主要就是sslSocketFactory()方法。是用來添加sslsocketFactory的,也就是客戶端發(fā)送的請求都等于手持了這樣的證書,這樣就可以和服務(wù)器交互了。
SslsocketFactory對象的獲取方法如下:
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
請求體和響應(yīng)體封裝:
{
"page":2,
"pageSize":10
}
Json體類似如上所示的可以封裝為如下的請求體/響應(yīng)體,此處可以借用GsonFormat插件,輸入json體就可以快速生產(chǎn)請求體/響應(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);
}
使用說明:
此接口用來聲明請求類型,call聲明的類型是返回體的bean類,@header是請求的頭,@body是返回體的類型。
請求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;
}
}
使用說明:
此接口用來聲明請求model的,主要用到的是上面的服務(wù)接口。 此類主要用來獲取網(wǎng)絡(luò)請求體的。
響應(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;
}
}
使用說明:
通常在發(fā)送網(wǎng)絡(luò)請求的時候只有兩種結(jié)果,一是請求發(fā)送失敗,二是服務(wù)器接收到了請求并且響應(yīng)了。
onFailure()主要用來處理請求發(fā)送失敗的情況,onResponse()用來處理服務(wù)器的響應(yīng)內(nèi)容。
response.raw().code()的值就是我們在網(wǎng)站開發(fā)中遇到的標(biāo)識代碼,200代表成功返回消息體,404代表api路徑?jīng)]找到(api路徑配置出錯是會導(dǎo)致這樣的情況,當(dāng)然也可能是服務(wù)器的環(huán)境出了問題,導(dǎo)致手機訪問不到),500代表的是服務(wù)器內(nèi)部錯誤(請求中的參數(shù)配置有誤會導(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,"用戶名或密碼錯誤");
materialDialog.dismiss();
}else if (loginResponse.getErrcode() == 999){
materialDialog.dismiss();
ToastUtils.showToast(LoginActivity.this,"服務(wù)器異常,請稍后再試");
}
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ù)器異常,請稍后再試");
mMoneyTV.setText("0.00");
} else if (balanceResponse.getErrcode() == 403) {
ToastUtils.showToast(BalanceActivity.this,"登錄已失效,請重新登錄");
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();
}
});
}
使用說明:
這段代碼使用的是自己封裝的響應(yīng)事件回調(diào)類,當(dāng)然也可以用第二張圖retrofit默認(rèn)的那套,用自己封裝的有個好處就是404not found 可以處理進(jìn)行操作,如果用默認(rèn)的那套,在404的時候這段代碼就會崩潰。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android自定義view實現(xiàn)圓形waveview
這篇文章主要為大家詳細(xì)介紹了Android自定義view實現(xiàn)圓形waveview,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01
Android編程實現(xiàn)圖標(biāo)拖動效果的方法
這篇文章主要介紹了Android編程實現(xiàn)圖標(biāo)拖動效果的方法,涉及Android事件響應(yīng)及圖標(biāo)變換的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11
Android中pendingIntent與Intent的深入分析
這篇文章主要介紹了Android中pendingIntent的深入分析的相關(guān)資料,需要的朋友可以參考下2017-04-04
Android中使用Spinner實現(xiàn)下拉列表功能
Spinner是一個列表選擇框,會在用戶選擇后,展示一個列表供用戶進(jìn)行選擇。下面通過本文給大家實例詳解android中使用Spinner實現(xiàn)下拉列表功能,一起看看吧2017-04-04
Android巧用DecorView實現(xiàn)對話框功能
本篇文章主要介紹了Android巧用DecorView實現(xiàn)對話框功能,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
Android 修改現(xiàn)有ROM資源文件如何實現(xiàn)
這篇文章主要介紹了Android 修改現(xiàn)有ROM資源文件如何實現(xiàn)的相關(guān)資料,這里對修改ROM 文件進(jìn)行了詳細(xì)的步驟介紹,需要的朋友可以參考下2016-12-12

