Retrofit源码分析

Retrofit源码分析


前言

retrofit是基于okhttp3的(推荐先看OkHttp3源码解析),没图说个jb?下面附图一张(感谢这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)这篇博客友情提供); 接着我会用一个简单的实例,进行源码的分析以及讲解。
这里写图片描述

实例

  1. 导入一些必要的第三方库

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
  2. 接着创建ServiceInterface(动态代理接口)

public interface TestApi {
    @GET("data/福利/{number}/{page}")
    Call<GankBeautyResult> getBeauties(@Path("number") int number, @Path("page") int page);
}

3.请求实例

Retrofit retrofit = new Retrofit.Builder()
        .client(new OkHttpClient())
        .baseUrl("http://gank.io/api/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build();
TestApi testApi = retrofit.create(TestApi.class);
Call<GankBeautyResult> call = testApi.getBeauties(100, 1);

call.enqueue(new Callback<GankBeautyResult>() {
    @Override
    public void onResponse(Call<GankBeautyResult> call, Response<GankBeautyResult> response) {
        System.out.println("response content:" + response.body().beauties.size());
    }
    @Override
    public void onFailure(Call call, Throwable t) {

    }
});

实例源码分析

初始化retrofit实例

根据实例代码,通过建造者模式创建一个retrofit实例如下;其中baseUrl属性是必须指定的;由1行,Retrofit.Builder()实例方法首先通过Platform的静态方法get()得到Android实例(通过18-57行),然后调用重载方法Builder(Platform);由2-4行,一些参数的赋值;由5行,由60-62行,baseUrl属性是必须指定的;由64-67行,如果没有指定OkHttpClient,那么就创建一个OkhttpClient;由69-72行,通过刚刚得到的Android实例获取callbackExecutor;由75-79行,一些CallAdapter和Converter的保存,最后把上述传入创建Retrofit对象。

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://gank.io/api/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build();

public Builder() {
  this(Platform.get());
}

Builder(Platform platform) {
      this.platform = platform;
      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
}

 static Platform get() {
    return PLATFORM;
  }

private static final Platform PLATFORM = findPlatform();

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

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      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);
      }
    }
  }

 public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
}

代理代理(接口的代理)

由1行,通过动态代理,生成代理对象testApi; 动态代理的原理自行Google,当调用该代理对象的方法时,会执行内部匿名类InvocationHandler的invoke(…)方法。
由30行,我们看invoke方法里面,由16-21行,一些必要的拦截;由22行,通过loadServiceMethod(method)方法获取ServiceMethod对象;由32-44行,该方法通过Map

TestApi testApi = retrofit.create(TestApi.class);

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() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, 
          @Nullable 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);
          }
        });
  }

  Call<GankBeautyResult> call = testApi.getBeauties(100, 1);

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

        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {
            result = new ServiceMethod.Builder<>(this, method).build();
            serviceMethodCache.put(method, result);
          }
        }
        return result;
  }

  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) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }

     @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
     }

进行请求

由上,call为ExecutorCallbackCall对象,由14行,传入一个接口调用delegate.enqueue(callback)这里的delegate是OkHttpCall对象;由38-71行,我们看OkHttpCall.enqueue(final Callback callback)方法,由40-43行,是不是很熟悉?是的这里就是开始调用OkHttp3了(推荐看OkHttp3源码解析)通过request和OkHttpClient创建okhttp3.Call对象;由49行,这里就是调用Okhttp3异步请求,我们直接看onResponse回调方法是怎么处理的;由54行,通过parseResponse(okhttp3.Response)中body通过serviceMethod.toResponse(catchingBody)处理成对应的实例body;然后将该body跟okhttp3.Response一起封装成retrofit的Response对象;由59行,通过callSuccess(Response response)最终回调结果;由15-25行,ExecutorCallbackCall.enqueue方法的callback接口的onResponse回调方法收到对应的结果,这里会通过callbackExecutor切换到ui主线程执行用户传入的接口回调方法;callbackExecutor为MainThreadExecutor对象(上面有提到,你可以往上翻)该对象通过execute(runnable)继而通过方法里的 handler.post(r)切换到了主线程。(handler创建的时候是指定了主线程looper)->(你可以看看Handler消息机制以及源码分析Handle Looper MessageQueue)

call.enqueue(new Callback<GankBeautyResult>() {
        @Override
        public void onResponse(Call<GankBeautyResult> call, Response<GankBeautyResult> response) {
            System.out.println("response content:" + response.body().beauties.size());
        }
        @Override
        public void onFailure(Call call, Throwable t) {

        }
});

 @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");
      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);
            }
          });
        }
      });
    }

    @Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");
    okhttp3.Call call;
    ...
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
     ....

    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    .....
    });
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值