android Retrofit2+okHttp3使用总结
使用前准备
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'
网络框架搭建
服务创建类封装(HTTP):
publicclassServiceGenerator{
publicstaticfinalStringAPI_BASE_URL="";
publicstaticintREAD_TIMEOUT=60;
publicstaticintWRIT_TIMEOUT=60;
publicstaticintCONNECT_TIMEOUT=60;
privatestaticOkHttpClient.BuilderhttpClient=newOkHttpClient.Builder()
.readTimeout(READ_TIMEOUT,TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(CONNECT_TIMEOUT,TimeUnit.SECONDS);
privatestaticRetrofit.Builderbuilder=
newRetrofit.Builder()
.baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create());
publicstaticScreateService(ClassserviceClass){
returncreateService(serviceClass,null);
}
publicstaticScreateService(ClassserviceClass,finalStringauthToken){
if(authToken!=null){
httpClient.addInterceptor(newInterceptor(){
@Override
publicResponseintercept(Interceptor.Chainchain)throwsIOException{
Requestoriginal=chain.request();
//Requestcustomization:addrequestheaders
Request.BuilderrequestBuilder=original.newBuilder()
.method(original.method(),original.body());
Requestrequest=requestBuilder.build();
returnchain.proceed(request);
}
});
}
OkHttpClientclient=httpClient
//日志拦截器
.addInterceptor(newHttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
Retrofitretrofit=builder.client(client).build();
returnretrofit.create(serviceClass);
}
}
使用说明:
API_BASE_URL用来配置api主地址
READ_TIMEOUT用来配置读取超时时间
WRIT_TIMEOUT用来配置写超时时间
CONNECT_TIMEOUT用来配置连接超时时间
addConverterFactory()用来设置解析器,此处我们设置的是gson的解析
addInterceptor()用来设置日志拦截器
服务创建类封装(HTTPS):
publicclassHttpsServiceGenerator{
publicstaticfinalStringAPI_BASE_URL="";
publicstaticintREAD_TIMEOUT=250;
publicstaticintWRIT_TIMEOUT=250;
publicstaticintCONNECT_TIMEOUT=250;
privatestaticOkHttpClient.BuilderhttpClient=newOkHttpClient.Builder();
privatestaticRetrofit.Builderbuilder=
newRetrofit.Builder()
.baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create());
publicstaticScreateService(ClassserviceClass){
returncreateService(serviceClass,null);
}
publicstaticScreateService(ClassserviceClass,finalStringauthToken){
if(authToken!=null){
httpClient.addInterceptor(newInterceptor(){
@Override
publicResponseintercept(Interceptor.Chainchain)throwsIOException{
Requestoriginal=chain.request();
//Requestcustomization:addrequestheaders
Request.BuilderrequestBuilder=original.newBuilder()
.method(original.method(),original.body());
Requestrequest=requestBuilder.build();
returnchain.proceed(request);
}
});
}
Retrofitretrofit=builder.client(getUnsafeOkHttpClient()).build();
returnretrofit.create(serviceClass);
}
privatestaticOkHttpClientgetUnsafeOkHttpClient(){
try{
//Createatrustmanagerthatdoesnotvalidatecertificatechains
finalTrustManager[]trustAllCerts=newTrustManager[]{
newX509TrustManager(){
@Override
publicvoidcheckClientTrusted(java.security.cert.X509Certificate[]chain,StringauthType)throwsCertificateException{
}
@Override
publicvoidcheckServerTrusted(java.security.cert.X509Certificate[]chain,StringauthType)throwsCertificateException{
}
@Override
publicjava.security.cert.X509Certificate[]getAcceptedIssuers(){
X509Certificate[]x509Certificates=newX509Certificate[0];
returnx509Certificates;
}
}
};
//Installtheall-trustingtrustmanager
finalSSLContextsslContext=SSLContext.getInstance("SSL");
sslContext.init(null,trustAllCerts,newjava.security.SecureRandom());
//Createansslsocketfactorywithourall-trustingmanager
finalSSLSocketFactorysslSocketFactory=sslContext.getSocketFactory();
OkHttpClientokHttpClient=
newOkHttpClient.Builder()
.readTimeout(READ_TIMEOUT,TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(CONNECT_TIMEOUT,TimeUnit.SECONDS)
.addInterceptor(newHttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.sslSocketFactory(sslSocketFactory)
.hostnameVerifier(newHostnameVerifier(){
@Override
publicbooleanverify(Stringhostname,SSLSessionsession){
returntrue;
}
}).build();
returnokHttpClient;
}catch(Exceptione){
thrownewRuntimeException(e);
}
}
}
使用说明:
可以看出https和http的服务类主要区别在于retrofit对象的构造方法不同。
主要就是sslSocketFactory()方法。是用来添加sslsocketFactory的,也就是客户端发送的请求都等于手持了这样的证书,这样就可以和服务器交互了。
SslsocketFactory对象的获取方法如下:
finalSSLContextsslContext=SSLContext.getInstance("SSL");
sslContext.init(null,trustAllCerts,newjava.security.SecureRandom());
finalSSLSocketFactorysslSocketFactory=sslContext.getSocketFactory();
请求体和响应体封装:
{
"page":2,
"pageSize":10
}
Json体类似如上所示的可以封装为如下的请求体/响应体,此处可以借用GsonFormat插件,输入json体就可以快速生产请求体/响应体bean类。
publicclassGetTradeDetailRequest{
/**
*page:2
*pageSize:10
*/
privateintpage;
privateintpageSize;
publicintgetPage(){
returnpage;
}
publicvoidsetPage(intpage){
this.page=page;
}
publicintgetPageSize(){
returnpageSize;
}
publicvoidsetPageSize(intpageSize){
this.pageSize=pageSize;
}
}
服务接口封装:
publicinterfaceBalanceService{
@GET("balance")
CallgetBalance(@Header("AccessToken")StringaccessToken);
@POST("balance/detail")
CallgetDetail(@Header("AccessToken")StringaccessToken,@BodyGetTradeDetailRequesttradeDetailRequest);
}
使用说明:
此接口用来声明请求类型,call声明的类型是返回体的bean类,@header是请求的头,@body是返回体的类型。
请求model封装:
publicclassBalanceModel{
privatestaticBalanceModelbalanceModel;
privateBalanceServicemBalanceService;
/**
*Singleton
*/
publicstaticBalanceModelgetInstance(Contextcontext){
if(balanceModel==null){
balanceModel=newBalanceModel(context);
}
returnbalanceModel;
}
publicBalanceModel(Contextcontext){
mBalanceService=HttpsServiceGenerator.createService(BalanceService.class);
}
publicCallgetBalanceResponseCall(StringaccessToken){
CallbalanceResponseCall=mBalanceService.getBalance(accessToken);
returnbalanceResponseCall;
}
}
使用说明:
此接口用来声明请求model的,主要用到的是上面的服务接口。此类主要用来获取网络请求体的。
响应事件回调类封装:
publicabstractclassCallbackimplementsretrofit2.Callback { @Override publicvoidonResponse(Call call,Response response){ if(response.raw().code()==200){ Log.i("internetresponse","200"); onSuccess(response); }elseif(response.raw().code()==404){ Log.i("internetresponse","404"); onNotFound(); } } @Override publicvoidonFailure(Call call,Throwablet){ } publicabstractvoidonSuccess(Response response); publicvoidonNotFound(){ return; } }
使用说明:
通常在发送网络请求的时候只有两种结果,一是请求发送失败,二是服务器接收到了请求并且响应了。
onFailure()主要用来处理请求发送失败的情况,onResponse()用来处理服务器的响应内容。
response.raw().code()的值就是我们在网站开发中遇到的标识代码,200代表成功返回消息体,404代表api路径没找到(api路径配置出错是会导致这样的情况,当然也可能是服务器的环境出了问题,导致手机访问不到),500代表的是服务器内部错误(请求中的参数配置有误会导致这样的情况)。
代码中使用:
privatevoidhttpLoginRequest(Stringphone,Stringpassword){
mPushToken=mPushAgent.getRegistrationId();
GetLoginRequestloginRequest=newGetLoginRequest();
loginRequest.setPhone(phone);
loginRequest.setPassword(password);
loginRequest.setPushtoken(mPushToken);
loginRequest.setCarrier(mCarrier);
finalCallcallLogin=loginModel.getLoginResponseCall(loginRequest);
callLogin.enqueue(newCallback(){
@Override
publicvoidonFailure(Callcalllist,Throwablet){
ToastUtils.showToast(LoginActivity.this,"网络服务异常");
materialDialog.dismiss();
callLogin.cancel();
}
@Override
publicvoidonSuccess(Responseresponse){
GetLoginResponseloginResponse=response.body();
userBean=loginResponse.getData();
if(loginResponse.getErrcode()==0){
ToastUtils.showToast(LoginActivity.this,"登录成功");
ActivityCollector.finishAll();
startActivity(newIntent(LoginActivity.this,MapActivity.class));
AppConfigUtils.getInstanse(LoginActivity.this).clearAll();
AppConfigUtils.getInstanse(LoginActivity.this).setUserBean(userBean);
materialDialog.dismiss();
}elseif(loginResponse.getErrcode()==203){
ToastUtils.showToast(LoginActivity.this,"用户名或密码错误");
materialDialog.dismiss();
}elseif(loginResponse.getErrcode()==999){
materialDialog.dismiss();
ToastUtils.showToast(LoginActivity.this,"服务器异常,请稍后再试");
}
callLogin.cancel();
}
@Override
publicvoidonNotFound(){
materialDialog.dismiss();
ToastUtils.showToast(LoginActivity.this,"404");
super.onNotFound();
callLogin.cancel();
}
});
}
privatevoidhttpBalanceRequest(StringaccessToken){
BalanceModelbalanceModel=BalanceModel.getInstance(getApplicationContext());
finalCallbalanceResponseCall=balanceModel.getBalanceResponseCall(accessToken);
balanceResponseCall.enqueue(newCallback(){
@Override
publicvoidonResponse(Callcalllist,Responseresponse){
GetBalanceResponsebalanceResponse=response.body();
if(balanceResponse.getErrcode()==0){
mMoneyTV.setText(balanceResponse.getData().getBalance());
}elseif(balanceResponse.getErrcode()==999){
ToastUtils.showToast(BalanceActivity.this,"服务器异常,请稍后再试");
mMoneyTV.setText("0.00");
}elseif(balanceResponse.getErrcode()==403){
ToastUtils.showToast(BalanceActivity.this,"登录已失效,请重新登录");
AppConfigUtils.getInstanse(BalanceActivity.this).clearAll();
ActivityCollector.finishAll();
LoginActivity.actionStart(BalanceActivity.this,mPhone,"");
}
balanceResponseCall.cancel();
}
@Override
publicvoidonFailure(Callcalllist,Throwablet){
ToastUtils.showToast(BalanceActivity.this,"网络服务异常");
balanceResponseCall.cancel();
}
});
}
使用说明:
这段代码使用的是自己封装的响应事件回调类,当然也可以用第二张图retrofit默认的那套,用自己封装的有个好处就是404notfound可以处理进行操作,如果用默认的那套,在404的时候这段代码就会崩溃。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。