Retrofit源码解析

Retrofit的使用

1.创建网络请求的接口

public interface GetApi {

    /**
     * 获取用户信息
     * @return
     * @Query 注解
     */
    @GET("getUserInfo")
    Call<UserInfo> getUserInfo(@Query("id") String userId);

}

2. 创建Retrofit实例

private Retrofit retrofit;
retrofit = new Retrofit.Builder()
    .baseUrl("http://mock-api.com/2vKVbXK8.mock/")
    .addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build();

 使用构造者模式

addConverterFactory(GsonConverterFactory.create())

添加转换器工厂,以支持不同的数据模式。

addCallAdapterFactory(RxJava2CallAdapterFactory.create())

添加网络请求的适配器,支持RxJava

3.创建网络请求接口的实例

private GetApi getApi;
getApi = retrofit.create(GetApi.class);

 4.发送网络请求,处理服务器返回的数据

getApi.getUserInfo(userid).enqueue(new Callback<UserInfo>() {
    @Override
    public void onResponse(Call<UserInfo> call, Response<UserInfo> response) {
        if (response != null && response.body() != null) {
            //此处为获取到的信息
            UserInfo userInfo = response.body();
        }
    }

    @Override
    public void onFailure(Call<UserInfo> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t);
    }
});

这是一个完整的Retrofit请求的过程。

Retrofit真正的网络请求工作是交给okhttp去完成的,retrofit是专注于接口的封装。

使用动态代理将注解翻译成一个一个okhttp请求。最后由线程池来执行okhttp请求。

动态代理的知识

什么叫代理模式

代理模式:为其他对象提供一种代理,用以控制这个对象的访问。海外购物的时候找代购帮我们买东西,代购怎么买的过程我们不需要关心,我们只在意结果。

静态代理

有一个学生管理类,提供了“添加学生”和“删除学生”两个方法:

public interface IStudentService {
void insertStudent();
void deleteStudent();
}
public class StudentService implements IStudentService {
public void insertStudent(){
//添加学生
}
public void deleteStudent(){
//删除学生
}
}

如果我们想要在添加/删除的前后分别打上日志,应我们该怎么做呢?

public class StudentService implements IStudentService {
public void insertStudent(){
System.out.println("准备添加学生");
//添加学生
System.out.println("添加学生成功");
}
public void deleteStudent(){
System.out.println("准备删除学生");
//删除学生
System.out.println("删除学生成功");
}
}

如果过两天,我们又打算在添加/删除方法上添加事务呢?

这样又需要修改添加/删除方法,我们要遵循对扩展开放,对修改封闭,此外,日志和事务不属于学生管理类的业务范畴,交给专门的类来处理。

如此一来代理就排上了用场,无论是日志还是事务可以交给代理类来解决。

public class StudentServiceProxy implements IStudentService {
IStudentService studentService;
public StudentServiceProxy(IStudentService studentService){
this.studentService = studentService;
}
@Override
public void insertStudent() {
System.out.println("准备添加学生");
studentService.insertStudent();
System.out.println("添加学生成功");
}
@Override
public void deleteStudent() {
System.out.println("准备删除学生");
studentService.deleteStudent();
System.out.println("删除学生成功");
}
}

在上面的代码中,代理类和业务类继承了相同的接口,并且重写了添加/删除学生的方法。

在重写的方法中,我们不仅可以调用业务类的原有方法,并且在调用的前后可以进行额外的处理,比如加上日志、事务等等。

这样一来,在客户端当中,我们只要创建了代理类,就可以像使用业务类一样使用它,非常方便:

public class Client {
public static void main(String[] args) {
IStudentService studentServiceProxy = new StudentServiceProxy(new StudentService());
studentServiceProxy.insertStudent();
studentServiceProxy.deleteStudent();
}
}

像这样通过代理类给对象的行为添加辅助功能的解决方案,就是代理模式。

如果我们要对已有的方法做改进,有2种选择,第一种是去修改原来的方法,第二种就是使用代理类,调用原来的方法,对产生的结果进行控制。不修改原来的方法的情况下,增强方法和功能。

动态代理

如果有许多的类都需要增加日志,比如学生管理类、教师管理类、物资管理类、难道要给每一个业务类都配一个代理类吗?

如果需要灵活的代理,我们需要做到动态代理。

所谓动态代理,在程序运行时创建的代理方式

以Java语言为例,Java为我们提供了十分方便的创建动态代理的工具包。当我们生成动态代理的时候,我们需要使用到InvocationHandler接口和Proxy类。

具体的实现过程如下:

1.实现InvocationHandler接口,定义调用方法前后所做的事情:

public class MyInvocationHandler implements InvocationHandler {
private Object object;
public MyInvocationHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "方法调用前");
method.invoke(object, args);
System.out.println(method.getName() + "方法调用后");
return null;
}
}

2.通过Proxy类的newProxyInstance方法,动态生成代理对象:
public class Client {
public static void main(String[] args) {
IStudentService studentService = new StudentService();
InvocationHandler studentInvocationHandler = new MyInvocationHandler(studentService);
IStudentService studentServiceProxy = (IStudentService) Proxy.newProxyInstance(studentInvocationHandler.getClass().getClassLoader(), studentService.getClass().getInterfaces(), studentInvocationHandler);
studentServiceProxy.insertStudent();
studentServiceProxy.deleteStudent();
}
}

  @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
        return null;
    }

proxy:代理的真实对象

method:调用的真实对象的某一个方法

args:代理真实对象的某一个方法的所有参数

为什么要这么做?

生成相对应的代理类,会调用invoke方法

接下来看看Retrofit 源码

public final class Retrofit {
  private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
  private final okhttp3.Call.Factory callFactory;
  private final HttpUrl baseUrl;
  private final List<Converter.Factory> converterFactories;
  private final List<CallAdapter.Factory> adapterFactories;
  private final Executor callbackExecutor;
  private final boolean validateEagerly;

七个关键成员变量的作用

serviceMethodCache: 缓存

callFactory : 生产OKHttpClient

baseUrl : 基地址

converterFactories: 数据转换器的工厂的集合 ,数据请求之后的response的转换,转换成我们能用的对象

adapterFactories: 网络适配器的工厂 生产CallAdapter RXJava

callbackExecutor : 执行回调 网络请求最终都是通过线程池加handler来进行调配的,能处理子线程和主线程切换的

validateEagerly: 标志位是否需要立即解析接口中的方法

构建者模式对成员变量的初始化

public static final class Builder {
private Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private List<Converter.Factory> converterFactories = new ArrayList<>();
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;

  Builder(Platform platform) {
    this.platform = platform;
  }

  public Builder() {
    this(Platform.get());
  }

静态内部类Builder

platform 适用的平台这里是Android

callFactory 请求网络的okhttp的工厂

converterFactories: 数据转换器的工厂集合 网络上获取的response转换成能用的json对象

adapterFactories: 网络请求适配器的工厂集合 call对象转换成Rxjava

callbackExecutor 异步回调的,默认是主线程的Executor,切换线程

 

看无参的Builder(),Platform 是单例

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
   Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }

通过反射 加载指定的类, 返回一个安卓对象

介绍Android类

static class Android extends Platform {
  @Override public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
  }

  @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
    return new ExecutorCallAdapterFactory(callbackExecutor);
  }

  static class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override public void execute(Runnable r) {
      handler.post(r);
    }
  }
}
   private final Handler handler = new Handler(Looper.getMainLooper());

Looper.getMainLooper()和主线程绑定

executor线程切换 回调方法在主线程.这个executor和我们的主线程所绑定了,就是可以在主线程中切换的原因

总结下:

1.配置平台类型的对象 Android

2.配置网路适配器的工厂 和数据转换器的工厂

3.executor

private Retrofit retrofit;
retrofit = new Retrofit.Builder()
    .baseUrl("http://mock-api.com/2vKVbXK8.mock/")
    .addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build();

看看这里的 .baseUrl()做了哪些事情

主要是将String类型的baseUrl转换成HttpUrl类型的baseUrl

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);
}
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;
}

判断最后一个是否以斜杠来结尾

private Retrofit retrofit;
retrofit = new Retrofit.Builder()
    .baseUrl("http://mock-api.com/2vKVbXK8.mock/")
    .addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build();

看看这里的addConverterFactory()做了哪些操作

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

 看下GsonConverterFactory.create()

  public static GsonConverterFactory create() {
    return create(new Gson());
  }

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

 private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }

使用gson来解析网络response的数据

private Retrofit retrofit;
retrofit = new Retrofit.Builder()
    .baseUrl("http://mock-api.com/2vKVbXK8.mock/")
    .addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build();

来看下.addCallAdapterFactory(RxJavaCallAdapterFactory.create())做了哪些操作

   public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
 
  private final @Nullable Scheduler scheduler;
  private final boolean isAsync;
}

RxJava中的调度器Scheduler 

了解下build方法完成retrofit对象的创建流程

    public Retrofit build() {
     //baseUrl不能缺
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      //可以看出retrofit是用OKHttp来完成网络请求的
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      //提供默认的回调方法执行器,异步请求的时候,子线程做耗时操作,要回到主线程做UI操作
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 添加默认的网络请求适配器
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

以上就完成了Retrofit的初始化的过程。

RxJavaCallAdapterFactory内部构造与工作原理

public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {

}
public interface CallAdapter<R, T> {

     Type responseType();
     T adapt(Call<R> call);

      abstract class Factory {

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

 
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    //获取原始类型
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}

网络请求接口实例解析

public interface GetApi {

    @GET("getUserInfo")
    Call<UserInfo> getUserInfo(@Query("id") String userId);

}
  public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          @Override public @Nullable Object invoke(Object proxy, Method method,
              @Nullable Object[] args) throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

参考文献:

https://juejin.cn/post/6919816939233607694

https://juejin.cn/post/6885358107996717064#heading-12

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值