Android小知识-剖析Retrofit中静态内部类Builder的三个方法

本平台的文章更新会有延迟,你们能够关注微信公众号-顾林海,包括年末前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,若是你们想获取最新教程,请关注微信公众号,谢谢!java

在上章节《Android小知识-剖析Retrofit中的网络请求流程以及相关参数》中介绍了Retrofit的成员变量,以及静态内部类Builder中的成员变量,本节继续讲解Builder类中的相关方法。web

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://icould.glh/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
复制代码

经过Builder的baseUrl方法来设置http的基地址,先进入baseUrl方法。json

public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      return baseUrl(httpUrl);
    }
复制代码

在baseUrl方法中,将传入的String类型的baseUrl经过HttpUrl的parse方法转换成HttpUrl对象,将转换后的httpUrl实例传入baseUrl方法,注意这里传入baseUrl方法的是HttpUrl对象,咱们继续看baseUrl(HttpUrl)方法。数组

public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }
复制代码

经过checkNotNull方法判断HttpUrl对象是否为空,接着经过HttpUrl的pathSegments()方法将url拆分红多个独立的碎片,为了方便比较,将建立Retrofit实例贴出来:服务器

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://icould.glh/")
复制代码

经过baseUrl方法设置http的url时,在最后是以'/'反斜杠结尾的,下面的if语句中判断拆分后的最后字符串是否为空,拆分后的数组最后一个为空,说明http的url是以'/'结尾,反之http的url不是以'/'结尾,就会抛出异常,最后将baseUrl赋值给Builder的成员变量baseUrl。微信

介绍完baseUrl方法,继续看下一个方法addConverterFactory方法:网络

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://icould.glh/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
复制代码

addConverterFactory方法是用于设置数据解析器,进入addConverterFactory方法看看到底作了哪些操做。ide

public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
复制代码

addConverterFactory方法所作的工做很简单,就是将factory添加到数据解析器工厂的集合中。回到前面addConverterFactory方法,看到传入的是GsonConverterFactory对象,而GsonConverterFactory对象是经过GsonConverterFactory的get()方法建立的,点进去看下。函数

public static GsonConverterFactory create() {
    return create(new Gson());
  }
复制代码

create方法内部先是建立了Gson对象,这个Gson就是goole提供的Gson,用于解析json数据用的,建立完Gson对象后调用create方法并传入刚建立后的Gson对象。ui

public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonConverterFactory(gson);
  }
复制代码

方法很简单,建立一个GsonConverterFactory对象并返回,咱们进入GsonConverterFactory的构造函数中。

private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }
复制代码

GsonConverterFactory的构造函数只作了赋值操做,将建立好的Gson对象赋值给GsonConverterFactory的成员变量gson。

介绍完addConverterFactory方法后,接着看addCallAdapterFactory方法:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://icould.glh/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
复制代码

addCallAdapterFactory方法用于设置适配的平台,这里使用的是RxJava平台,咱们看下addCallAdapterFactory的具体操做。

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
复制代码

代码仍是很简单,就是将factory添加到适配器工厂的集合中去。回到前面,看看addCallAdapterFactory方法传入的这个Factory,是经过RxJavaCallAdapterFactory工厂类的create()方法来建立的。

public static RxJavaCallAdapterFactory create() {
    return new RxJavaCallAdapterFactory(null, false);
  }
复制代码

create方法内部直接经过new关键字建立了RxJavaCallAdapterFactory对象。

public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
  ...
}
复制代码

RxJavaCallAdapterFactory继承了CallAdapter的内部类Factory。

先看CallAdapter的做用,CallAdapter做用就是经过Retrofit中Call转换成Java对象,Retrofit中的Call对象和OkHttp中的Call对象是不同的,Retrofit中的Call是对OkHttp中的Call进行了封装,也就是说经过Retrofit来进行网络请求,最终都是经过OkHttp来进行请求的。在转换Java对象前,须要先建立Retrofit中的Call对象,而后经过Call对象发送http请求,服务器会返回响应的数据,这个时候经过converter数据转换器,将服务器返回的Response转换成咱们须要的Java对象。

public interface CallAdapter<R, T> {

    Type responseType();

    T adapt(Call<R> call);


}
复制代码

在CallAdapter接口中定义了一个responseType()方法并返回Type类型,这个方法的做用就是返回解析后的类型。看下面网络请求接口:

public interface NetworkInterface {
    @GET("news/newsDetail")
    Call<MyResponse> getNewsDetails(@QueryMap Map<String,String> map);
}
复制代码

CallAdapter接口中的responseType方法返回的就是MyResponse这个类型的对象。

public interface CallAdapter<R, T> {

    Type responseType();

    T adapt(Call<R> call);


}
复制代码

继续看第二个方法adapt,这里的泛型T是指须要转换接口的返回类型,adapt方法传入一个Call对象,这个Call对象就是OkHttp的Call对象,若是对应的是RxJava的话,这里的T对应的就是RxJava当中的类型。

继续看CallAdapter内部类Factory:

public interface CallAdapter<R, T> {

    ...

    abstract class Factory {
        public abstract @Nullable retrofit2.CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
                                        Retrofit retrofit);

        ...

        protected static Class<?> getRawType(Type type) {
            return Utils.getRawType(type);
        }
    }
}
复制代码

get方法的做用是根据接口的返回类型以及注解类型来获得实际须要的CallAdapter;getRawType方法返回的是原始的类型。

RxJavaCallAdapterFactory实现Factory抽象类,用来提供具体的适配逻辑,回到RxJavaCallAdapterFactory,先看get方法的实现:

@Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        Class<?> rawType = getRawType(returnType);
        ...
        return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
                false);
    }
复制代码

在get方法中,先经过getRawType拿到原始数据类型,经过这个原始数据类型进行各类设置,最后建立RxJavaCallAdapter对象并返回。建立完RxJavaCallAdapter对象后,最终调用adapt方法将咱们的Call请求转换成每个平台所适用的类型。adapt方法在接口CallAdapter中定义的,在源码中找到RxJavaCallAdapter实现了CallAdapter接口,咱们看看RxJavaCallAdapter中的adapt实现。

@Override public Object adapt(Call<R> call) {
        Observable.OnSubscribe<Response<R>> callFunc = isAsync
                ? new CallEnqueueOnSubscribe<>(call)
                : new CallExecuteOnSubscribe<>(call);

        Observable.OnSubscribe<?> func;
        if (isResult) {
            func = new ResultOnSubscribe<>(callFunc);
        } else if (isBody) {
            func = new BodyOnSubscribe<>(callFunc);
        } else {
            func = callFunc;
        }
        Observable<?> observable = Observable.create(func);

        if (scheduler != null) {
            observable = observable.subscribeOn(scheduler);
        }
        if (isSingle) {
          return observable.toSingle();
       }
       if (isCompletable) {
          return observable.toCompletable();
        }
        return observable;
    }
复制代码

使用过RxJava的同窗应该对上面的代码很是熟悉了,将咱们传入的OkHttp的Call对象设置给OnSubscribe对象,接着建立Observable被观察者的实例,并将OnSubscribe与被观察者绑定,最后判断scheduler调度器是否为空,若是不为空,就调用observable的subscribeOn方法在指定的调度器执行操做。关于RxJava的相关知识后面会另开文章进行讲解,这里你们先有个印象,知道总体的流程便可。

到这里baseUrl、addConverterFactory以及addCallAdapterFactory方法就介绍完毕。


838794-506ddad529df4cd4.webp.jpg

搜索微信“顾林海”公众号,按期推送优质文章。

相关文章
相关标签/搜索