okhttp3 retrofit2 android Retrofit2+okHttp3使用总结
林水吉 人气:0使用前准备
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):
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)//设置读取超时时间 .writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//设置写的超时时间 .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() 用来设置解析器,此处我们设置的是gson的解析
addInterceptor() 用来设置日志拦截器
服务创建类封装(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)//设置读取超时时间 .writeTimeout(WRIT_TIMEOUT,TimeUnit.SECONDS)//设置写的超时时间 .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的服务类主要区别在于retrofit对象的构造方法不同。
主要就是sslSocketFactory()方法。是用来添加sslsocketFactory的,也就是客户端发送的请求都等于手持了这样的证书,这样就可以和服务器交互了。
SslsocketFactory对象的获取方法如下:
final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
请求体和响应体封装:
{ "page":2, "pageSize":10 }
Json体类似如上所示的可以封装为如下的请求体/响应体,此处可以借用GsonFormat插件,输入json体就可以快速生产请求体/响应体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; } }
服务接口封装:
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的,主要用到的是上面的服务接口。 此类主要用来获取网络请求体的。
响应事件回调类封装:
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; } }
使用说明:
通常在发送网络请求的时候只有两种结果,一是请求发送失败,二是服务器接收到了请求并且响应了。
onFailure()主要用来处理请求发送失败的情况,onResponse()用来处理服务器的响应内容。
response.raw().code()的值就是我们在网站开发中遇到的标识代码,200代表成功返回消息体,404代表api路径没找到(api路径配置出错是会导致这样的情况,当然也可能是服务器的环境出了问题,导致手机访问不到),500代表的是服务器内部错误(请求中的参数配置有误会导致这样的情况)。
代码中使用:
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,"网络服务异常"); 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,"服务器异常,请稍后再试"); } 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,"服务器异常,请稍后再试"); 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,"网络服务异常"); balanceResponseCall.cancel(); } }); }
使用说明:
这段代码使用的是自己封装的响应事件回调类,当然也可以用第二张图retrofit默认的那套,用自己封装的有个好处就是404not found 可以处理进行操作,如果用默认的那套,在404的时候这段代码就会崩溃。
加载全部内容