逃离Android使用思惟牢笼-Retrofit2.5工做原理

引言

  Retrofit是Square公司开发的一款针对Android网络请求的框架,遵循Restful设计风格,咱们查看 invoke 能够发现:底层基于OkHttp实现的 ,相比其余网络请求框架,有如下优点:java

  • 性能最好,速度最快(动态代理优点)
  • 简洁易用,代码简化
  • 解耦完全,职责细分
  • 易与其余框架联用(Rxjava)

固然也有弊端:由于高度封装,相对于 OkHttp ,扩展性变差了,不过总体能知足项目需求.今天我就带你们来看一下Retrofit到底是如何使用,以及内部工做原理node

一.概述

做用

  OKHttp 作的更加简洁,更加方便,同时影藏了oKHttp的某些功能。android

type-safe

  在运行的时候不会报类型错误,经过泛型策阅,将运行时异常提高到编译期异常。git

二.使用

1. 添加 retrofit 依赖
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
复制代码
2. 添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
复制代码
3. 建立实体类

  访问 小木箱 github 仓库,经过get请求获得了如下报文:github

而后,经过 Gsonformat 获得相关实体类对象:
class MicroKibacoRepo {


   private int id;
   private String node_id;
   private String name;
   private String full_name;
  // ---为了不浪费篇幅,省略无用代码--- 
}
复制代码
4. 建立⼀一个 interface 做为 Web Service 的请求集合,在⾥里⾯⽤注解(Annotation)写⼊须要配置的请求方法
public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<MicroKibacoRepo>> listRepos(@Path("user") String user);
}
复制代码
5. 在正式代码里⽤ Retrofit 建立出 interface 的实例
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

GitHubService service = retrofit.create(GitHubService.class);
复制代码
6. 调⽤建立出的 Service 实例的对应⽅法,建立出相应的能够⽤来发起网络请求的 Call 对象
Call<List<MicroKibacoRepo>> repos = service.listRepos("MicroKibaco");

复制代码
7. 使用 Call.execute() 或者 Call.enqueue() 来发起请求
repos.enqueue(new Callback<List<MicroKibacoRepo>>() {
            @Override
            public void onResponse(Call<List<MicroKibacoRepo>> call, Response<List<MicroKibacoRepo>> response) {

            }

            @Override
            public void onFailure(Call<List<MicroKibacoRepo>> call, Throwable t) {

            }
        });
复制代码

三.源码解析

读源码如何开始呢?api

1. 寻找入口

  一行一行读,确定是不可行的,太累了,并且脑容量不够,记不住,合适的读源码方式是从程序入口开始入手。当前功能开始读。网络

   当前请求的入口发生在enqueue, 那么,咱们就开始从这个Api入手读源码.框架

enqueue, 是进入队列的意思,进去查看,居然是个分布式

void enqueue(Callback<T> callback);
复制代码

若是出现相似抽象方法;就得往回看了,由于读不下去了ide

2. 寻找接口实现

因此咱们往上面找,上面的Api是 enqueue,去找 相关接口实现,找了半天,爱哭,接口实现是GithubService

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<MicroKibacoRepo>> listRepos(@Path("user") String user);
}
复制代码

而GithubService.java是我本身建立的,怎么办呢? 继续往回看,找呀找, 找到了Retrofit的初始化方法 create,整个源码我就不翻出来了,翻一翻关键的部分,其中须要讲述的APi有:

  • eagerlyValidateMethods
  • newProxyInstance
  • Platform
  • invoke
  • invokeDefaultMethod
public <T> T create(final Class<T> service) {
   
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) 
    
    // --------动态代理--------
    Proxy.newProxyInstance(
    // 提供动态类的实例
    service.getClassLoader(), 
    // 获取 GithubService 的实例,获取须要动态代理类的接口,在 retrofit.create 传入
    new Class<?>[] { service },
    // 
        new InvocationHandler() {
         // 判断接口平台,是JDK 7.0/8.0 或者 Android/IOS
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
            // 若是这个方法不是直接声明的,那么就直接调用了,兼容性,保护性,不至于越权
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
             // java 8 开始,接口运行有默认的方法实现了
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }
  
    static <T> void validateServiceInterface(Class<T> service) {
     // 1. 验证 GitHubService 是否为一个接口
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
     // 2.验证 GitHubService 是否继承其余接口,只接受原生接口
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }
  
  // 3. 在被初始化的时候,是有一个初始化过程,会去读注解,中间是有耗时的,分布式加载网络请求, validateEagerly 是方便调试的
    private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
复制代码

Platform.java 看一下相关实现,里面包含两个平台一个是 Java8 还有一个 Android,这个APi主要是平台标识,知道就好了,没什么好说的

private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
      // Android 平台
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
       // Java8 平台
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
复制代码

loadServiceMethod 里面也没有 invoke,咱们经过 parseAnnotations 去找 一下invoke试试看可否找到,

ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
复制代码

ServiceMethod.java里面,不过也是一个抽象方法 ,因而咱们往回看 parseAnnotations,看里面是否有 invoke 的逻辑实现,找到了,好家伙,parseAnnotations是ServiceMethod子类HttpServiceMethod实现方法,而HttpServiceMethod必定有invoke实现

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }
// 经过 parseAnnotations 去寻找 invoke实现
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract T invoke(Object[] args);
}
复制代码

不用说,我直接在HttpServiceMethod.java, ctr + f 搜,便搜到了invoke,原来底层真是经过OKHttp实现的:

final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
 // ----为了不浪费篇幅,省略若干无用代码----
 @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }
}
复制代码

上面我说过,看到抽象方法,往回看 ,因此咱们来看 okHttpCall,OKHttpCall实现了Call接口 ,重点说一下一下方法:

  • createRawCall
// OKhttp3的Call帮助Retrofit实现网络请求的Call
  private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }
复制代码
  • call.enqueue
call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
      
      // response 结果交给 Retrofit 使用
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }
复制代码

什么是动态代理?

  动态代理是建立一个对象,这个对象传入一个接口而且帮你实现每个接口的每个方法,而且这每个接口的每个方法都会指向每个接口每个方法的invoke方法。

  • callAdapter

HttpServiceMethod.java里面的构造方法, 咱们找到了 CallAdapter,而后去里面查看是经过 createCallAdapter返回的

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method) {
    Type returnType = method.getGenericReturnType();
    Annotation[] annotations = method.getAnnotations();
    try {
      // CallAdapter 建立
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }
复制代码

进入 Retrofit.java 查看一下:

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
  
    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
  
 // 经过 callAdapterFactories 获取 callAdapter
 
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
 // ----为了不浪费篇幅,省略若干无用代码----
  }
复制代码

callAdaperFactory是经过 Retrofit 的 build 方法构建而来.

public Retrofit build() {
  
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
复制代码

咱们看到 callAdaperFactory 经过 addAll 一次性添加过来,因此有咱们看一下defaultCallAdapterFactories方法.

@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
        @Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
      return Build.VERSION.SDK_INT >= 24
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
    }
复制代码

而后咱们再看一下 ExecutorCallAdapterFactory

未完待续~

相关文章
相关标签/搜索