Android 网络请求总结

1,193 阅读3分钟

Rxjava+retrofit+okhttp的网络请求框架

之需要注意的地方


1 retrofit和okhttp异步回调的线程问题:

  • okhttp异步调用后,callback运行在子线程
  • retrofit异步调用后,其callback运行在主线程,retrofit就是对okhttp的一系列封装,运用了大量设计模式,其回调结果最后通过handle传到了主线程,这点要注意,尤其在更新ui时
  • rxjava封装后,回调线程可以通过其线程调度来很方便的设置

2 rxjava 的Observable封装的 retrofit call的泛型参数:

  • TypeBody(class类):如

    public class Result{
        private String name;
        private String ID;
    }
    
    
    //在相应retrofit接口中
    @GET(.....)
    Observable<Result> Login()
    

    通过添加gson转换器,将网络请求响应中返回的json转换为相应的java类,方便操作,注意这个必须在创建retrofit是添加gson转换器.addConverterFactory(GsonConverterFactory.create())

  • ResponseBody(okhttp包下的)

    @GET(...)
    Observable<ResponseBody> Login()
    

    这个适用于你不需要将其转换成具体的类,只是想获取响应体,当让你也可以获取body后自己手动解析body数据

  • Response<T>(retrofit包下) 这个将所有响应结果都封装到了这个response里,他的泛型参数可以填ResponseBody或者class类,通过他不仅可以获取body,还可以获取响应码等。

3 Rxjava的网络请求错误处理

  • 注意,如果是用Response包裹的响应体,那么之前说过,所有东西都被包裹在了Response里,所以即使是错误的响应,如4××/5××,也会包裹在Response里,发送给onNext(),而不会发送给onError(),而错误的响应体可以通过
     if (e instanceof HttpException){
        (HttpException)e).response().errorBody()
      }
    
    获取错误的响应体。 而如果不是用Response包裹,那么除了2**的响应吗会进入onNext()里,其他的响应码都会直接进入onError()里,这样就中断了这个观察链

参考stackoverfollow

  • 关于rxjava的flatmap链式调用:flatmap可以解决回调地狱,解决连续进行网络请求的问题,如
      Observable.just("hello")
                  .flatMap(new Func1<String, Observable<?>>() {
                      @Override
                      public Observable<?> call(String s) {
                          Log.i(TAG, "call: flatmap  -----1");
                          s = "hellp flapmap1";
                          if (s != null)
                              return Observable.error(new NullPointerException("null test"));
                          return Observable.just(s);
                      }
                  }).flatMap(new Func1<Object, Observable<?>>() {
    
    
              @Override
              public Observable<?> call(Object o) {
                  Log.i(TAG, "call: flatmap-----2");
                  return Observable.just("33333");
              }
    
          }).subscribe(new Subscriber<Object>() {
    
    
              @Override
              public void onCompleted() {
                  Log.i(TAG, "onCompleted: ");
              }
    
              @Override
              public void onError(Throwable e) {
                  Log.i(TAG, "onError: call");
                  if (e instanceof NullPointerException)
                      Log.i(TAG, "onError: illegal   " + e.getMessage());
              }
    
              @Override
              public void onNext(Object o) {
                  Log.i(TAG, "onNext: ");
              }
          });
    
    第一个flatmap中抛出了一个异常,那么下一个flatmap就不会调用,直接进入了最后订阅的观察者中,进入onError()里。可见,即便你在flatmap里对上一个被观察者发送的结果进行了操作,但他并不算是一个观察者,只是对其进行了一部分处理,map等操作符也是这样,他们共同组成了一个长长的链,唯一的观察者在最后订阅的Subscriber中处理,所以如果中间任意环节出了异常,那么该链在此中断,直接进入最后观察者的onerror里。
    所以之前的如果用Response包裹,就不会中断观察链,你可以根据响应码做一些处理。

4 okhttp的拦截器及重定向处理

  • okhttp的拦截器是其责任链模式的重要实现,通过一个个拦截器将网络链接的各个部分,模块拆分开,分工明确
  • okhttp中对重定向的处理是通过其第一个内置的拦截器RetryAndFollowUpInterceptor实现的,他通过while循环来不断创建request请求资源,知道响应码为200(或错误),当然他也负责进行失败重试
  • 关于Application interceptors与Network Interceptors区别 他们其实都是用户自定义的拦截器,只是添加顺序不同,导致有区别 okhttp源码中的添加顺序:

可见Application interceptors第一个添加,而Network Interceptors添加在RetryAndFollowUpInterceptor等拦截器之后,所以Network Interceptors可以拦截到重定向的请求,而Application interceptors只能拦截到刚开始的请求和最后重定向后的结果

参考:博客