当前位置: 首页 > 编程笔记 >

android Retrofit2+okHttp3使用总结

朱通
2023-03-14
本文向大家介绍android Retrofit2+okHttp3使用总结,包括了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):

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的时候这段代码就会崩溃。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • OkHttp 是一个底层网络库(相较于 Cronet 或 Volley 而言),尽管它也包含了 SPDY 的支持。OkHttp 与 Glide 一起使用可以提供可靠的性能,并且在加载图片时通常比 Volley 产生的垃圾要少。对于那些想要使用比 Android 提供的 HttpUrlConnection 更 nice 的 API,或者想确保网络层代码不依赖于 app 安装的设备上 Android

  • 我在网络请求中使用了带有okhttp_3库的retrofit_2(beta4)。并且我需要缓存响应数据,以满足网络关闭的情况,并且应用程序必须显示来自上一个相同请求的响应数据。我找到的解决这个问题的所有指南都是使用okhttp lib(而不是okhttp_3)。我试图解决问题: 但这不起作用。当网络处于打开状态时,所有请求都能正常工作,但当网络处于关闭状态时,它们不能返回缓存数据。拜托,帮忙解决这

  • 创建okhttp3客户端,使用sni地址访问web服务器,但握手失败,错误消息为“javax.net.ssl.SSLHandShakeException:握手期间远程主机关闭连接”。 有人知道如何在okhttp3客户端代码中使用sni地址吗?

  • 问题内容: 我正在尝试固定服务器的自签名证书。我的OkHttpClient使用两个参数,第一个是ssl Socket Factory: 其次是证书固定器: 注意:如果我不添加certificatePinner,则一切正常。问题是执行请求时,将调用CertificatePinner.check(): 显然,如果我确实设置了一个(非空的)certificatePinner,则该方法不会在那里停止,而是

  • 目前,我使用的是Android改版2.0.0-beta4和OKHTTP3。我正在执行定义如下的@PUT请求: endpoint在这里:http://apps:8080/EmployeeSkillsService/EmployeeSkill。下面是PUT请求的日志输出: 我已经在Chrome上的Postman中验证了这个带有这些头和有效负载的endpoint多次工作。然而,当我使用reverfit时

  • 但是,如下所示的调用序列使用相同的TCP连接。 我还没有对此进行调试,但OkHttp似乎迫使我们首先在主线程上发出阻塞HTTP请求,以获得TCP连接上下文,然后与其他线程共享该上下文?或者,我是不是漏掉了什么?