Retrofit源码学习之一

我们从简单的使用开始

implementation 'com.squareup.retrofit2:retrofit:2.4.0'

Retrofit 使用方法注解的方式把HTTP API转化成Java接口。

首先我们声明接口

public interface GitHubService {
   //获取github上用户信息,把要请求的http api转化成Java接口。
   @GET("users/{user}")
   Call<ResponseBody> userInfo(@Path("user") String user);
}

Retrofit使用四部曲

  1. 构建一个Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .build();
  1. 生成一个GitHubService接口的实现
GitHubService service = retrofit.create(GitHubService.class);

Retrofit类生成GitHubService接口的实现。

  1. 创建一个请求
Call<ResponseBody> call = service.userInfo("humanheima");

4.同步或者异步执行请求

4.1 同步请求

try {
    Response<ResponseBody> response = call.execute();
} catch (IOException e) {
    e.printStackTrace();
}

注意不要在主线程直接调用,不然会抛出android.os.NetworkOnMainThreadException

4.2 异步执行

call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            ResponseBody body = response.body();
            if (body != null) {
                try {
                    Log.d(TAG, "onResponse: " + body.string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

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

        }
});

1.构建一个Retrofit实例。

首先看一下Retrofit.Builder类的构造函数

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

Builder(Platform platform) {
    this.platform = platform;
}

Retrofit.Builder类的构造函数内部初始化了一个Platform实例。Platform代表Retrofit的使用平台。我们在Android中使用Retrofit,平台就是Android。

static class Android extends Platform {
    //默认的回调执行器
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
    //看到了Handler。可以猜想,回调之所以是在主线程执行,还是使用handler来实现的  
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
          handler.post(r);
      }
    }
}

接下来看一下Retrofit.Builder类的build方法

public Retrofit build() {
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
    }
    //注释1处,初始化callFactory 
    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
        callFactory = new OkHttpClient();
    }
    //初始化回调执行器
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
        //注释2处,使用平台默认的回调执行器
        callbackExecutor = platform.defaultCallbackExecutor();
    }

    //注释3处,防御性拷贝callAdapterFactories,并添加默认的CallAdapter.Factory
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>
                                               (this.callAdapterFactories);
    callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    //注释4处,防御性拷贝converters,并添加内置的converter factory 
    List<Converter.Factory> converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());
    //首先添加内置的converter factory到converter factory list中
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    //创建Retrofit实例
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

注释1处,创建了一个OkHttpClient对象。

注释2处,如果没有传入回调执行器,则使用平台默认的回调执行器,在Android平台中就是一个MainThreadExecutor对象。

注释3处,添加了平台默认的CallAdapter.Factory。就是一个ExecutorCallAdapterFactory对象,传入的是MainThreadExecutor对象。

注释4处,首先添加了一个内置的Converter.Factory对象。是一个BuiltInConverters对象。

最后Retrofit.Builder类的build()方法返回了一个Retrofit实例。

Retrofit的构造函数

Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
      Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;//是一个OkHttpClient对象,用来创建请求。
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; 
    this.callAdapterFactories = callAdapterFactories; 
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
}

2. 生成一个GitHubService接口的实现

GitHubService service = retrofit.create(GitHubService.class);

Retrofit的create 方法

public <T> T create(final Class<T> service) {
    //1. 首先验证service是否合法
    Utils.validateServiceInterface(service);
    //2. 是否提前创建service里面的所有方法
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //3. 创建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, Object[] args)throws Throwable {
             // service的所有方法调用,最终会转发到这里
            // 如果是Object的方法,就正常调用
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //如果是default方法(Java8中的默认方法),Android中不用管,一定是false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //3.1
            ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) 
                loadServiceMethod(method);
            //3.2
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //3.3
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
      });
  }

create方法内部创建了我们传入的service接口的动态代理。就是说我们我们调用service中的任何方法,都会转发到这个动态代理的invoke方法中。

3. 创建一个请求

Call<ResponseBody> call = service.userInfo("humanheima");

这时方法就转发到service动态代理的invoke方法中了。

//3.1
ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);
//3.2
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//3.3
 return serviceMethod.callAdapter.adapt(okHttpCall);

3.1构建一个ServiceMethod实例,ServiceMethod把对接口方法的调用转为一个HTTP调用
//缓存ServiceMethod实例
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new
 ConcurrentHashMap<>();

Retrofit的loadServiceMethod方法

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

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

首先在缓存中查找method对应的ServiceMethod,如果缓存中存在就直接返回,否则创建一个ServiceMethod并加入缓存。每个ServiceMethod只会创建一次。

接下来看一下ServiceMethod.Builder这个类。ServiceMethod.Builder负责检查接口方法上的注解,来构造一个可重复使用的服务方法。这个过程需要用到代价非常昂贵的反射操作,所以最好是只构建一个方法一次,然后重复使用它。Builder的实例不能被重用。

ServiceMethod.Builder的构造函数

Builder(Retrofit retrofit, Method method) {
    this.retrofit = retrofit;
    this.method = method;
    this.methodAnnotations = method.getAnnotations();
    this.parameterTypes = method.getGenericParameterTypes();
    this.parameterAnnotationsArray = method.getParameterAnnotations();
}

ServiceMethod.Builder的build方法简化版

public ServiceMethod build() {
    //1. 创建callAdapter
    callAdapter = createCallAdapter();
    //在这个例子中responseType就是ResponseBody
    responseType = callAdapter.responseType();
    ...
    //2. 创建responseConverter
    responseConverter = createResponseConverter();
    //3. 处理方法注解
    for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
    }
    ...
    int parameterCount = parameterAnnotationsArray.length;
    //4. 创建parameterHandlers
    parameterHandlers = new ParameterHandler<?>[parameterCount];
    for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
    }
    ...
    //5. 返回一个ServiceMethod实例
    return new ServiceMethod<>(this);
}

  1. 创建callAdapter。CallAdapter对象把一个类型参数为R的retrofit2.Call转化成T类型的对象(Call<R>转化成T)。CallAdapter的实例由构建Retrofit时候通过{Retrofit.Builder#addCallAdapterFactory(Factory)}方法设置的{CallAdapter.Factory}创建。

ServiceMethod.Builder类的createCallAdapter方法简化版

private CallAdapter<T, R> createCallAdapter() {
    //获取方法返回类型,在这个例子中,返回类型是Call<ResponseBody>
    Type returnType = method.getGenericReturnType();
    ...
    //获取方法注解
    Annotation[] annotations = method.getAnnotations();
    try {
      //注释1处,根据方法的返回类型和方法注解返回CallAdapter
      return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) {
        throw methodError(e, "Unable to create call adapter for %s", returnType);
    }
}

注释1处,根据方法的返回类型和方法注解返回CallAdapter。

Retrofit的callAdapter方法

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
}

Retrofit的nextCallAdapter方法简化版

 public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, 
    Type returnType, Annotation[] annotations) {
   
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
        //注释1处,遍历callAdapterFactories,返回合适的CallAdapter
        CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
        if (adapter != null) {
            return adapter;
        }
    }
}

Retrofit的callAdapter()方法内部会去遍历callAdapterFactories这个list,根据方法返回类型和注解,返回合适的callAdapter。

在上面的分析中,当我们构建一个默认的Retrofit实例的时候,在Retrofit.Builder的build()方法内部默认添加了一个平台相关的CallAdapter.Factory而Android平台相关的默认的CallAdapter.Factory就是一个ExecutorCallAdapterFactory对象。ExecutorCallAdapterFactory这个类暂且不去管他。默认情况下ServiceMethod 的callAdapter就是ExecutorCallAdapterFactory的get方法返回的对象。

  1. 创建Converter<ResponseBody, T> responseConverter。负责把okhttp3.ResponseBody转化为T类型的对象。
private Converter<ResponseBody, T> createResponseConverter() {
    Annotation[] annotations = method.getAnnotations();
    try {
        //注释1处,根据方法的返回类型和注解返回Converter
        return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { 
        throw methodError(e, "Unable to create converter for %s", responseType);
    }
}

可见responseConverter也是由Retrofit提供的。

public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, 
    Annotation[] annotations) {

    return nextResponseBodyConverter(null, type, annotations);
}

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
       Converter.Factory skipPast, Type type, Annotation[] annotations) {
 
    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
         //注释1处,遍历converterFactories,找到合适的converter
        Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
        if (converter != null) {
            return (Converter<ResponseBody, T>) converter;
        }
    }
}

Retrofit的responseBodyConverter()方法内部会去遍历converterFactories这个list,根据方法返回类型和注解,返回合适的responseConverter。
在上面的分析中,当我们构建一个默认的Retrofit实例的时候,在Retrofit.Builder的build()方法内部传入了一个内置的BuiltInConverters对象。BuiltInConverters这个类暂且不去管它。现在为ServiceMethod找到了responseConverter。

  1. parseMethodAnnotation:负责解析检查方法注解,暂且略过。

  2. 创建parameterHandlers,内部会创建Converter,负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;这个过程暂且不去看。

每个参数都会有一个 ParameterHandler,由 ServiceMethod的parseParameter 方法负责创建,其主要工作就是解析每个参数使用的注解类型(诸如 Path,Query,Field 等),对每种类型进行单独的处理。API 方法中除@Body@PartMap@Part类型的参数,都利用 Converter.Factory.stringConverter 进行转换。而@Body@PartMap@Part类型的参数则利用 Converter.Factory.requestBodyConverter 进行转换。

现在ServiceMethod.Builder的build()方法可以返回一个实例了。

public ServiceMethod build() {
    //5. 返回一个ServiceMethod实例
    return new ServiceMethod<>(this);
}

ServiceMethod的构造函数

ServiceMethod(Builder<R, T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers;
}
3.2是创建一个OkHttpCall实例
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
3.3 返回结果
return serviceMethod.callAdapter.adapt(okHttpCall);

ServiceMethod的adapt方法

T adapt(Call<R> call) {
    return callAdapter.adapt(call);
}

默认情况下,ServiceMethod的callAdapter就是ExecutorCallAdapterFactory的get方法返回的对象。

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);
    //返回一个CallAdapter实例。
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
          return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
            //注释1处,返回ExecutorCallbackCall实例
            return new ExecutorCallbackCall<>(callbackExecutor, call);
        }
    };
}

ExecutorCallAdapterFactory的get方法创建了一个CallAdapter的匿名对象。该对象的
adapt方法返回了一个ExecutorCallbackCall对象。

注意,到这里Call<ResponseBody> call = service.userInfo("humanheima");方法最终返回的是一个ExecutorCallbackCall<T>对象。ExecutorCallbackCall类是ExecutorCallAdapterFactory的静态内部类,实现了retrofit2.Call接口。

ExecutorCallbackCall的构造函数

static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;//回调执行器
    final Call<T> delegate;//一个OkHttpCall对象

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

注意一下,在Android平台下,我们传入的回调执行器是一个MainThreadExecutor对象,用来将执行结果post到主线程,我们下面分析。

4. 现在到了Retrofit使用四部曲的第四步,执行请求。

4.1 同步请求execute

ExecutorCallbackCall的execute方法就是调用了代理对象的execute方法。

@Override 
public Response<T> execute() throws IOException {
    return delegate.execute();
}

OkHttpCall的execute方法

@Override 
public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      //1. 一个请求只能被执行一次
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      //...
      call = rawCall;
      if (call == null) {
        try {
          //2. 创建一个okhttp3.Call
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
    //3. 转换okhttp3.Call的执行返回的响应
    return parseResponse(call.execute());
  }
  1. 一个请求只能被执行一次。
  2. 调用createRawCall方法,创建一个okhttp3.Call

OkHttpCall的createRawCall方法

private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = serviceMethod.toCall(args);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

createRawCall方法返回的是一个okhttp3.RealCall的实例。

  1. 转换okhttp3.Call的执行返回的响应retrofit2.Response<T>
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    //临时保存原始响应体
    ResponseBody rawBody = rawResponse.body();

    //移除响应体的源(唯一有状态的对象),这样我们就可以传递响应。
    //移除rawResponse的本来的响应体,传入一个没有内容的响应体
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    //...
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      //注释1处,把原始响应体转化成我们希望的数据类型
      T body = serviceMethod.toResponse(catchingBody);
      //构建一个成功的响应体返回,并把转化后的数据作为响应体。
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than
     // indicating it was a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

parseResponse方法首先会对响应做一些预处理,如果没有什么异常的话,就构建一个成功的响应返回。

在注释1处,在这个例子中,我们期望返回的数据类型就是okhttp3.ResponseBody

ServiceMethod的toResponse方法

R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
}

内部调用了responseConverter的convert方法,在上面的分析中,我们知道默认情况下responseConverter就是BuiltInConverters的responseBodyConverter方法返回的对象。

final class BuiltInConverters extends Converter.Factory {
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      //我们的返回类型是ResponseBody
      if (type == ResponseBody.class) {
        //注释1处,我们只看没有使用Streaming注解的情况
        return Utils.isAnnotationPresent(annotations, Streaming.class)
            ? StreamingResponseBodyConverter.INSTANCE
            : BufferingResponseBodyConverter.INSTANCE;
      }
      if (type == Void.class) {
        return VoidResponseBodyConverter.INSTANCE;
      }
      return null;
    }
}

在注释1处,我们只看没有使用Streaming注解的情况,返回的是一个BufferingResponseBodyConverter对象。

BufferingResponseBodyConverter类

static final class BufferingResponseBodyConverter implements Converter<ResponseBody, ResponseBody> {

    static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      try {
          // 注释1处,缓存整个响应体避免将来出现IO异常
          return Utils.buffer(value);
      } finally {
          value.close();
      }
  }
}

在注释1处,就是返回了整个响应体。

static ResponseBody buffer(final ResponseBody body) throws IOException {
    Buffer buffer = new Buffer();
    body.source().readAll(buffer);
    return ResponseBody.create(body.contentType(), body.contentLength(), buffer);
}

最终执行的结果是返回了一个Response<ResponseBody>对象。

4.2 异步请求execute

ExecutorCallbackCall内部的execute就是调用了代理对象的execute方法。执行完毕后会使用传入的callbackExecutor执行线程切换。

@Override 
public void enqueue(final Callback<T> callback) {
    //调用代理的enqueue方法,并在执行完毕后使用回调执行器切换线程
    delegate.enqueue(new Callback<T>() {
      @Override 
      public void onResponse(Call<T> call, final Response<T> response) {
          //注释1处,执行成功,使用回调执行器切换线程
          callbackExecutor.execute(new Runnable() {
          @Override 
          public void run() {
              if (delegate.isCanceled()) {
                //如果请求被取消了,抛出IOException
                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);
            }
        });
      }
  });
}   

OkHttpCall的enqueue方法

@Override 
public void enqueue(final Callback<T> callback) {
 
    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          //1.构建一个okhttp3.Call   
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    //...
    if (canceled) {
      call.cancel();
    }
    //2. 使用okhttp3.Call的enqueue方法
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          //把okhttp3.Response转换成retrofit2的Response  
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        //3. 成功的回调
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          //4. 失败的回调  
          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();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

OkHttpCall的enqueue方法先判断请求是否执行过了。如果没有执行,就构建一个okhttp3.Call的实例,加入一个异步请求队列,执行成功或者失败后会调用传入的callback的对应方法。

如果执行成功,调用传入的callback的onResponse方法。

delegate.enqueue(new Callback<T>() {
      @Override 
      public void onResponse(Call<T> call, final Response<T> response) {
          //注释1处,调用回调执行器execute的方法切换线程
          callbackExecutor.execute(new Runnable() {
          @Override 
          public void run() {
              if (delegate.isCanceled()) {
                //如果请求被取消了,抛出IOException
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }
    //...
}

在注释1处,使用回调执行器切换线程。在Android中就是一个MainThreadExecutor对象。我们看一下MainThreadExecutor的execute方法。

static class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override public void execute(Runnable r) {
        handler.post(r);
    }
}

内部就是通过handler来切换到了主线程。

listCall.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            //回到主线程执行
            ResponseBody body = response.body();
            if (body != null) {
                try {
                    Log.d(TAG, "onResponse: " + body.string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
             //回到主线程执行
        }
});

至此:Retrofit使用四部曲就分析完了。

参考链接

  1. Retrofit
  2. Android Retrofit 2.0使用
  3. github
  4. 拆轮子系列:拆 Retrofit
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容