Retrofit简单原理分析

14 篇文章 0 订阅

Retrofit原理分析

之前学习了怎么使用Retrofit,现在来学习它的原理。Retrofit使用接口+注解的形式来定义一个网络请求,在通过OkHttp来执行网络请求。现在有很多开源使用了注解Annotation,如Dagger2、ButterKnife等,以及Retrofit。所不同的是他们利用注解干的事却不一样。Dagger2、ButterKnife他们在编译期间就处理注解生成代码,提供依赖注入。Retrofit则是则运行期间处理注解,通过动态代理的方式来提供AOP能力。

Retrofit至少使用了5中设计模式:

1)建造者模式

2)动态代理模式

3)静态代理模式

4)适配器模式

5)工厂模式

下面将一步一步来简单分析Retrofit的源码

//使用建造者模式创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_URL)
                .addConverterFactory(GsonConverterFactory.create()).build();
//创建Github接口对象
Github github = retrofit.create(Github.class);
Call<List<Contributor>> call = github.getContributors("square", "retrofit");
//设置回调接口,下载任务加入到网络请求队列中,底层调用了OkHttp来完成网络请求
call.enqueue(new Callback<List<Contributor>>() {...});

这里最核心的过程就是:

Github github = retrofit.create(Github.class);
Call<List<Contributor>> call = github.getContributors("square", "retrofit");

它使用了动态代理的方式来创建一个网络请求任务,create方法返回了一个动态代理对象github。

Java动态代理就是Java开发给了开发人员一种可能:当你要调用某个类的方法前,插入你想要执行的代码比如你要执行某个操作前,你必须要判断这个用户是否登录,或者你在付款前,你需要判断这个人的账户中存在这么多钱。这么简单的一句话,我相信可以把一个不懂技术的人也讲明白Java动态代理是什么东西了。那么问题来了,我们的接口是Github,但是并未提供Github的实现类,动态代理对象到底代理的是哪个具体类的方法啊?

从下面的代码看出,实际上在动态代理时,并未执行service的method方法,而是在调用invoke方法中另起一套逻辑,这就是AOP编程的精髓,横切一刀插入自己的代码,这也是为啥只需要提供一个接口就OK的原因!当然Retrofit也留了一手,你可以定义一个实现了Github接口的类,这样动态代理时调用的方法就是自己定义的方法。

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);//判断接口是否非法
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //Retrofit最核心的代码,通过动态代理的方式来创建一个继承了Github接口的实现类
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, Object... args)
              throws Throwable {
            //如果service类已经实现了Github接口,则不会调用service类中的方法
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //创建ServiceMethod对象
            ServiceMethod serviceMethod = loadServiceMethod(method);
            //创建OkHttpCall对象,该对象内部维护了OkHttp的RealCall对象
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //返回Call<List<COntributor>>对象,这句代码不简单,采用了工厂模式、静态代理和适配器模式
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

  //ServiceMethod是个什么东西,将接口方法转换成一个HTTP Call
  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);//缓存机制
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

下面来看看serviceMethod.callAdapter.adapt(okHttpCall)这句代码后面的设计模式

这里写图片描述
ExecutorCallAdapterFactory为工厂类,创建CallAdapter对象

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

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

      @Override public <R> Call<R> adapt(Call<R> call) {
        //返回代理类
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

  static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;//主线程执行器MainThreadExecutor,调用主线程Handler分发事件
    final Call<T> delegate;//被代理的对象,即我们的okhttpcall对象

    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");
     //调用被代理对象的enqueue方法,这里是okhttpcall类,处理结果通过callbackExecutor返回给主线程调用
      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()) {  
                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);
            }
          });
        }
      });
    }

    ...
  }
}

上文提到的ExecutorCallAdapterFactory和MainThreadExecutorAndroid类为Retrofit提供的默认实现,当然我们可以自己定义相应的类来覆盖默认实现。这些默认实际上是由一个叫Platform的类提供的,在Android平台上,使用的一个叫做Android的类,它这个继承自Platform,定义了默认的CallAdapterFactory和默认的Executor

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

new ServiceMethod.Builder(this, method).build()背后做了啥?ServiceMethod也采用了建造者模式来创建ServiceMethod对象。

public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();//反射获取注解
      this.parameterTypes = method.getGenericParameterTypes();//反射获取参数类型
      this.parameterAnnotationsArray = method.getParameterAnnotations();//反射获取参数的注解
    }
public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        ...
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);//处理方法的注解
      }

      ...

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          ...
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
        //处理参数的注解
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      ...

      return new ServiceMethod<>(this);
    }

将任务传递给OkHttp处理

public void enqueue(final Callback<T> callback) {
    ...
    //引入了OkHttp
    okhttp3.Call call;
    Throwable failure;
    //同时只能允许一个Request存在
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();//创建OkHttp请求对象RealCall
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }
    //将请求任务加入队列,请求结果通过回调接口返回给客户端
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        ...
        callback.onResponse(OkHttpCall.this, response);
      }

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

private okhttp3.Call createRawCall() throws IOException {
    //构建一个HTTP请求
    Request request = serviceMethod.toRequest(args);
    //相当于调用了new OkHttpClient().newCall(request),创建一个OkHttp Call
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

在Retrofit的默认实现中,CallBack回调运行在主线程上,而不用管retrofit是否是在主线程中调用。

1)因为Retrofit底层调用的是OkHttp,而OkHttp的回调并非运行在主线程,所以Retrofit对它进行了封装,使用主线程Handler进行分发,使得CallBack回调运行在主线程上

2)也就说不管在哪个线程中调用retrofit,我们都可以在Retrofit的回调中直接操作UI,这个特性是不是很屌!

public class MainActivity extends AppCompatActivity {
    public static final String API_URL = "https://www.baidu.com";
    private TextView text;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text=(TextView)findViewById(R.id.text);

        new Thread(new Runnable() {
            @Override
            public void run() {
                //子线程中使用retrofit
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(API_URL)
                        .addConverterFactory(GsonConverterFactory.create()).build();
                Github github = retrofit.create(Github.class);

                Call<List<Contributor>> call = github.getContributors("square", "retrofit");
                call.enqueue(callback);
            }
        }).start();
    }

    private Callback<List<Contributor>> callback=new Callback<List<Contributor>>() {
        @Override
        public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
            //直接进行UI操作,是OK的
            text.setText("contributor");
        }

        @Override
        public void onFailure(Call<List<Contributor>> call, Throwable t) {
            Log.e("contributor number", "failure");
        }
    };
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值