Retrofit源码简单分析

本文深入讲解Retrofit,一个基于OkHttp的网络请求库,通过JDK动态代理实现接口调用。文章涵盖Retrofit的基本使用、依赖添加、接口定义及网络请求流程,同时解析其源码实现,帮助理解运行期动态代理的机制。
摘要由CSDN通过智能技术生成

基础介绍

Retrofit 是对okhttp的封装,使用了大量的设计模式,核心原理:运行期,JDK动态代理。Retrofit官网

JDk动态代理实现步骤

  • 新建接口类,添加接口方法(不继承其他接口)
  • 新建接口实现类,实现接口
  • 新建代理类实现反射包java.lang.reflect.InvocationHandle的invoke方法,接口类的实现都由invoke代理,可在方法前后添加补充操作等。

Retrofit简单例子使用

	 1:添加网络权限  
	  <uses-permission android:name="android.permission.INTERNET" />
	 2:添加依赖:
	  implementation 'com.squareup.retrofit2:retrofit:2.6.1'
      implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
      implementation 'com.squareup.retrofit2:adapter-rxjava:2.6.1'
     3:基本使用
      A:新建接口类(通过用户类型返回用户集合)
      public interface GithubService {
   		 @GET("users/{user}/repos")
   		 Call<List<User>> listRepos(@Path("1") String userType);
	}
	B:简单使用:
	   User user =new User();
       user.setType("1");
	   Retrofit retrofit =new Retrofit.Builder()
                //基本地址,和接口注解的地址拼接成完整的请求地址
                .baseUrl("https://api.xxx.com/")
                //数据转换工厂
                .addConverterFactory(GsonConverterFactory.create())
                //请求call适配器,如将使用Rxjava
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        //接口实例(通过jdk动态代理)
        GithubService githubService =retrofit.create(GithubService.class);
        githubService.listRepos(user.getType()).enqueue(new Callback<List<User>>() {
            @Override
            public void onResponse(Call<List<User>> call, Response<List<User>> response) {

            }

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

            }
        });

Retrofit部分源码分析

使用上面的简单例子分析:基本解析为代码上的注释

1:通过构建者模式创建Retrofit对象
A: 点击Retrofit先大致看下Retrofit的属性
Retrofit retrofit =new Retrofit.Builder().build();

public final class Retrofit {
 //缓存ServiceMethod网络请求方法
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
//网络请求Call,默认为Okhtp的Call 
  final okhttp3.Call.Factory callFactory;
  //网络请求地址
  final HttpUrl baseUrl;
  //类型转换工厂集合,将返回的ResponseBody转换成java对象,即请求方法的返回类型
  final List<Converter.Factory> converterFactories;
  //请求CAll转换工厂,将Retrofit的Call转换成其他请求的CAll,如Rxjava
  final List<CallAdapter.Factory> callAdapterFactories;
  //线程调度器,子线程执行完网络请求,切换成回UI显示就是使用此对象
  final @Nullable Executor callbackExecutor;
  //迫切验证标志位,提前完成ServiceMethod
  final boolean validateEagerly;
  .....
  }
B:进入Builder(),只是一个平台适配,如Android 、Java8等
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) {
    }
    return new Platform();
  }
C:进入build()

此处调用Retrofit的构造方法进行创建Retrofit对象,没有添加转换等工厂的话则使用默认的

2:Retrofit重点 在运行期通过jdk动态代理进行接口实现类创建,查看retrofit.create方法
GithubService githubService =retrofit.create(GithubService.class);

public <T> T create(final Class<T> service) {
	//1:service.isInterface()检验定义的接口是否是借口类型  
	//2:service.getInterfaces().length > 0 校验是否是单纯的接口,未继承其他接口
    Utils.validateServiceInterface(service);
    //是否需要提前解析接口中的请求方法
    if (validateEagerly) {
      //先从缓存Map serviceMethodCache 中查找,没有的话则通过parseAnnotations方法生成
      //ServiceMethod(ServiceMethod位包含所有请求信息的方法对象)
      eagerlyValidateMethods(service);
    }
    //getClassLoader 将.java转为.class
    //new Class<?>[] { service }   前面定义的接口文件
    //InvocationHandler  通过实现invoke方法 实现前面接口的内方法
    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.
            //如果是默认的方法toString()等则直接调用实现
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //平台默认方法 platform.isDefaultMethod(method) 点击进入直接返回就是false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //重点方法
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }
3: loadServiceMethod(method)方法创建ServiceMethod

读取接口中的方法转换成ServiceMethod,前面的迫切validateEagerly也是调用这个方法

  ServiceMethod<?> loadServiceMethod(Method method) {
  //先从缓存map中查找
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
      //缓存中没有则通过parseAnnotations转换成拥有所有请求信息的方法对象ServiceMethod,继而放入缓存map
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
4: 查看invoke方法
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

 @Override final @Nullable ReturnT invoke(Object[] args) {
 //得到retrofit2.Call对象 ,用于之后网络请求enqueue等方法的使用
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    //通过这个adapt 将call转换成新的retrofit.call对象,如rxjava的obervable等
    //使用这个call调用同步异步网络请求方法时,通过ServiceMethod相关创建一个Okhttp3的CAll对象来实现请求
    //由后台发起网络请求,返回后再主线程调用回调方法,实现线程切换(callbackExecutor)
    return adapt(call, args);
  }
5:最后调用同步异步方法就是将使用okhttp3的Call对象进行网络请求
@Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
   	......
      if (call == null && failure == null) {
        try {
        //创建Okhttp3的CAll对象
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
  	 ......
  	 //okhttp3的CAll进行请求网络
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }
	......
    });
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值