(Retrofit系列一)玩转Retrofit的执行器 ------ OkHttpCall

清新一刻

生活有时就是这么残酷,可能没人关心你的努力,大家只看最后的结果。成年人的世界没有“容易”二字!所谓无心插柳,都是努力后的水到渠成。


背景

相信现在Android在做网络方面的内容时,首先想到的就是Retrofit。为什么呢?
我这里总结了两条原因:
1、OkHttp用其强大的功力成功打入Android框架内部,(对于OkHttp还不太熟悉的朋友,建议先去了解一下,如果想对它的内部代码了解的,请看OKhttp源码系列文章
2、Retrofit就是对Okhttp的再封装,加上其通过注解的方式设计API并构造请求报文。完美的体现了简单易用,功能强大八个字。


正文

今天准备搞一搞Retrofit的执行器 —— OkHttpCall。顾名思义,执行器就是要来执行请求的,执行的方式有两种:
①同步执行;
②异步执行
这两种执行方式也是我们今天主要的分析内容,通过分析执行方式来了解Retrofit的执行器和Okhttp的执行器有什么关系。
在分析的过程中我会省略部分代码,目的是便于查看主要分析内容。

先来看一下Retrofit的基本用法

第一步、定义请求接口
public interface RequestInterface {

    @GET("/login/login")
    Call<ResponseBody> getMethod(@Field("username") String userName, @Field("password") String password);
}

第二步、实例化请求接口
   Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(sBaseUrl)
                .build();
   RequestInterface requestInterface = retrofit.create(RequestInterface.class);

第三步、执行请求
 Call<ResponseBody> call = requestInterface .getMethod("","");
        try {
            Response response = call.execute();//执行同步请求
        } catch (IOException e) {
            e.printStackTrace();
        }
            /*执行异步请求*/
           call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

            }

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

            }
        });

现在需要找到分析源码的入口,第一步就是定义一个接口,没什么东西。第二步实例化Retrofit并通过.create(class )得到接口对象。都知道接口是不能实例化对象的,那么这里是怎么做的呢?跟进去看看

 public <T> T create(final Class<T> service) {
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          @Override public Object invoke(Object proxy, Method method, Object... args)
              throws Throwable {
            ServiceMethod serviceMethod = loadServiceMethod(method);
            // 看这里!!! ,OkHttpCall。 就是我们要分析的执行器
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

动态代理!原来是通过动态代理的方式去实例化接口对象。大家可以看上面我加注释的地方,就是Retrofit执行器的部分。那我们看看这个类的内部是怎样的。

final class OkHttpCall<T> implements Call<T> {

  private volatile boolean canceled;//执行器是否被取消执行
  private okhttp3.Call rawCall; //这是真正的执行器 
  private boolean executed; // 执行器是否正在执行

 /*复写克隆方法,实例化新的OkHttpCall执行器*/
  @Override public OkHttpCall<T> clone() {
    return new OkHttpCall<>(serviceMethod, args);
  }

  /*异步执行*/
  @Override public void enqueue(final Callback<T> callback) {
    okhttp3.Call call;
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true; // 标识该执行器正在执行
      call = rawCall; // 得到OkHttp.call 
      if (call == null) {
        try {
          call = rawCall = createRawCall(); //如果为空就创建OkHttp.call
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) { // OkHttp.call 构造失败
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) { // 用户取消了执行器的执行
      call.cancel(); //去执行OkHttp.call 的取消行为
    }
    //OkHttp.call 真正的执行过程
    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) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

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

  /*同步执行*/
  @Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
    return parseResponse(call.execute());
  }

上面的代码我省略了很多,今天只抓主要内容。通过上面的规整,相信对OkHttp有过了解的朋友(没有了解过的朋友,请参看这篇文章OkHttp3源码(八) —— RealCall ),一眼就看出来了,OkHttpCall其实就是对OkHttp中RealCall的封装。将对OkHtpCall相关方法的调用(主要是execute()和enqueue(callback)两个方法)转交给OkHttp的RealCall相关方法。如果你对OkHttp的RealCall有过了解,那么到现在就对Retrofit执行器的源码分析完啦。 哈哈哈。。。。 是不是超简单。
这里OkHttpCall实现了Call接口,这个接口也很简单,就是定义了执行器的主要方法,看一下内容:

public interface Call<T> extends Cloneable {
  Response<T> execute() throws IOException;
  void enqueue(Callback<T> callback);
  boolean isExecuted();
  void cancel();
  Request request();
}

对于OkHttpCall今天就分析到这里,一句话总结:
OkHttpCall就是对OkHttp的RealCall的封装,最终执行都要OkHttp的RealCall来完成。所以对OkHttp的RealCall不了解的强烈建议去看
OkHttp3源码(八) —— RealCall


最后一问

我们回头再看看请求接口的定义,大家有没有想过,请求接口中方法的返回值到底是怎么来的,它必须是Call类型嘛?实际类型参数必须是ResponseBody嘛?

public interface RequestInterface {

    @GET("/login/login")
    Call<ResponseBody> getMethod(@Field("username") String userName, @Field("password") String password);
}

对于这个问题的答案我会在下篇博文中给出,相信看完下篇博文后,你会恍然大悟,原来与此。。。。。。

猜你喜欢

转载自blog.csdn.net/look_Future/article/details/81431438