Retrofit网络请求源码解析

栏目: Android · 发布时间: 7年前

内容简介:buid方法主要是构建一个真正的retrofit对象,加载适配器,转化器,callbackExecutor线程池,baseUrl等基本数据动态代理的核心方法,都会调用invoke,前面会加一些方法校验,而且retrofit同样支持android和java,所以也对平台做了封装,同时也加map缓存对应的代理对象加了一个同步锁,防止多线程的数据混乱问题,map缓存增加执行速度,构建之后同样加入map中去
/**
     * 初始化Retrofit
     */
    public static void init() {
        okHttpClient = HttpsUtils.getOKHttpClient();
        //设置Retrofit
        Retrofit client = new Retrofit.Builder()
                .baseUrl(HOST)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(okHttpClient)
                .build();
        //创建业务请求对象
        api = client.create(RequestApi.class);
    }
复制代码

2. Retrofit:build()方法组装数据以及添加适配和转化器

public Retrofit build() {
      //校验baseUrl
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //获取回调工厂,默认使用okhttp
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //添加线程池
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // 调用相关的适配器
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // 执行相关的转换器
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

buid方法主要是构建一个真正的retrofit对象,加载适配器,转化器,callbackExecutor线程池,baseUrl等基本数据

3.创建的入口(Retrofit create())

public <T> T create(final Class<T> service) {
    //检测是否是对应的接口
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      // 接口方法的缓存
      eagerlyValidateMethods(service);
    }
    //核心方法,动态代码相关方法
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          //获取对应的支持的平台 android java
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, 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);
            }
            //真正执行的方法
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
复制代码

动态代理的核心方法,都会调用invoke,前面会加一些方法校验,而且retrofit同样支持android和java,所以也对平台做了封装,同时也加map缓存对应的代理对象

4.loadServiceMethod加载服务方法

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;
    //加一个异步锁
    synchronized (serviceMethodCache) {
      //从的map中去拿
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
复制代码

加了一个同步锁,防止多线程的数据混乱问题,map缓存增加执行速度,构建之后同样加入map中去

5.查看ServiceMethod对象的创建方法Builder

public ServiceMethod build() {
      //构建响应Call的适配器,可以使用者通过addCallAdapterFactory() 工厂类添加
      callAdapter = createCallAdapter();
      //.....响应适配器的返回类型校验
      // 创建响应的Converter变换器 可通过addConverterFactory 工厂类添加
      responseConverter = createResponseConverter();

      //一系列的请求注解校验,具体看源码

      return new ServiceMethod<>(this);
    }
复制代码

构建响应的适配器和转换器,这些都可以被使用者通过工厂类从外部传进来

6. Retrofit nextCallAdapter() 创建适配器

ServiceMethod类:
private CallAdapter<T, R> createCallAdapter() {
      //获取接口指定的返回类型,Call或者是Observatble
      Type returnType = method.getGenericReturnType();
     //省略部分校验
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }
   //Retrofit的callAdapter方法
  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

   //省略
  }
    
复制代码

createCallAdapter校验返回值类型 之后会回调Retrofit的callAdapter方法之后执行适配器list中的适配器get方法

7.ExecutorCallAdapterFactory的get方法,之后调用线程池的创建方法

@Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
      //创建线程池
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

 
复制代码

8.call.enqueue(new Callback)开始真正请求数据,调用ExecutorCallbackCall的enqueue方法

static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override public void enqueue(final Callback<T> callback) {
      if (callback == null) throw new NullPointerException("callback == null");
      调用okhtt.Call方法里面的enqueue
      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

   //省略
  }
复制代码

进入了okhttp的请求中

9.把子线程请求的数据回调给主线程

这里感觉比较巧妙,基本都是使用handler,在Platform类中定义android平台时可以看到如下一段代码刚好和上面的ExecutorCallbackCall代理类delegate.enqueue(new Callback())呼应

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());
     //执行execute用handler的post方法到主线程
      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
复制代码

利用主线程的handler的post方法在执行execute的时候把数据返回主线程


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Developing Large Web Applications

Developing Large Web Applications

Kyle Loudon / Yahoo Press / 2010-3-15 / USD 34.99

As web applications grow, so do the challenges. These applications need to live up to demanding performance requirements, and be reliable around the clock every day of the year. And they need to withs......一起来看看 《Developing Large Web Applications》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具