Rx系列retrofitandroid 开发

Retrofit解析6之面向接口编程

2017-06-27  本文已影响415人  隔壁老李头

整体Retrofit内容如下:

从本文开始,开始正式解析Retrofit源码,本文的结构如下:

1、解析思路
2、Call接口
3、CallAdapter接口
4、Callback接口
5、Converter接口
6、ExecutorCallAdapterFactory类
7、Platform类
8、HttpException类
9、面向接口编程

一、解析思路:

(一)、假设

在讲解,解析思路之前,我们先想一下,那么想什么那?如果让你"设计"一个类似Retrofit的库,你要怎么"设计"那?
注意是重点是 "设计" ,不是 "写"
那怎么 "设计" 那?那我先说我的思路,如果是我,我先想摸清需求
需求如下:

所以如果我让我设计这么一个库,必须先写三个接口,每个接口对应上面的一个问题。这里我们又想到一个Call和转换,是两个需求,根据单一原则,应该是四个接口
分别是:

所以我在设计的时候,肯定要设计这四个接口,然后在围绕这四个接口进行操作,这是我的设计思想,那你们的那?

下面看下他的类目录结构


Retrofit类.png

如上图所示,有4个接口

二、Call接口

(一)、思考

两个问题:

————————分割线,思考上面的问题——————————

不知道你们的想法,不过我先说下我的想法

第一个问题 我是这么想的

这个Call 肯定模拟了一个客户端发起请求到服务器,然后服务器响应数据到客户端的整个流程。通过这个Call我们可以获取相应的请求和相应的信息。

第二个问题 我是这样想的

既然是模拟了整个请求和响应逻辑,所以肯定要设计一个发起请求的方法,来模拟发请求;既然是请求,所以必然包含一个同步请求的方法,表征同步请求,设计一个异步请求的方法,表征一个异步请求;还要设计一个取消请求的的方法,表征一个取消请求的方法。我能想到就是这么多了,你们的那?

OK,那我们来看下这个接口的源码看下Retrofit是怎么设计的。

(二)、来看下接口的源码

/**
 * An invocation of a Retrofit method that sends a request to a webserver and returns a response.
 * Each call yields its own HTTP request and response pair. Use {@link #clone} to make multiple
 * calls with the same parameters to the same webserver; this may be used to implement polling or
 * to retry a failed call.
 *
 * <p>Calls may be executed synchronously with {@link #execute}, or asynchronously with {@link
 * #enqueue}. In either case the call can be canceled at any time with {@link #cancel}. A call that
 * is busy writing its request or reading its response may receive a {@link IOException}; this is
 * working as designed.
 *
 * @param <T> Successful response body type.
 */
public interface Call<T> extends Cloneable {
  /**
   * Synchronously send the request and return its response.
   *
   * @throws IOException if a problem occurred talking to the server.
   * @throws RuntimeException (and subclasses) if an unexpected error occurs creating the request
   * or decoding the response.
   */
  Response<T> execute() throws IOException;

  /**
   * Asynchronously send the request and notify {@code callback} of its response or if an error
   * occurred talking to the server, creating the request, or processing the response.
   */
  void enqueue(Callback<T> callback);

  /**
   * Returns true if this call has been either {@linkplain #execute() executed} or {@linkplain
   * #enqueue(Callback) enqueued}. It is an error to execute or enqueue a call more than once.
   */
  boolean isExecuted();

  /**
   * Cancel this call. An attempt will be made to cancel in-flight calls, and if the call has not
   * yet been executed it never will be.
   */
  void cancel();

  /** True if {@link #cancel()} was called. */
  boolean isCanceled();

  /**
   * Create a new, identical call to this one which can be enqueued or executed even if this call
   * has already been.
   */
  Call<T> clone();

  /** The original HTTP request. */
  Request request();

老规矩先看下类的注释
我简单的翻译一下:
通过调用Retrofit的方法向web服务器发送请求并返回响应。每一次调用都产生自己的HTTP请求和对应的响应 对儿。如果出现了在避免轮询或者失败重试的情况,可以 调用clone()方法 复制 可以对具有相同的web服务器进行 具有相同参数的 请求。
同步调用 采用execute方法,异步采用enqueue方法,在任何情况下, 一个请求Call 都有可以通过cancel取消,一个Call在写入请求或读取响应的时候是可能产生IOExcetption的,这是再正常不过的了。
参数<T> 是成功的响应体类型

看下他的方法

方法.png

和大家设计的一样吗?我是少了三个方法,分别是

这里温馨提示下:

Request request();

里面的返回值是okhttp3.Request。这里返回是okHttp的request。大家怎么看这个情况,我的理解是在接口层面指定了okHttp的request,则指明了底层的请求只能使用okHttp了

PS:大家注意一下这个接口和okhttp3.Call的接口基本上一致,只不过多了一个clone()方法。

这个接口,目前就研究结束了,不知道大家怎么看待这个接口,希望大家看完这个接口的介绍,心里对Call这个接口有一个比较深刻的认识

三、CallAdapter接口

(一)、思考

同样两个问题?

————————分割线,思考上面的问题——————————

不知道你们的想法,不过我先说下我的想法
第一个问题 我是这么想的

我们知道retrofit是支持RxJava的,那么如果一个RxJava是需要转化成一个Retrofit中的Call<T>,那肯定需要一个适配器,把一个RxJava的Observable适配成一个Retrofit的Call<T>,所以设计这个类的主要目的就是适配让Retrofit的Call<T>对业务层的请求适配,这样整个结构更清晰。

第二个问题 我是这样想的

首先上面说了,既然是适配,肯定要有一个方法要去做适配把Retrofit的Call<T>适配成业务方自定义的"Call"。其次,大家知道Retrofit的Call<T>的泛型T是response的Body,这个类型是泛型,所以最后反序列化的时候需要反序列化成一个对象,这个需要指定这个对象的类型,所以还应该获取这个类的具体"类型"。

这是我之前的想法,大家的想法如何?那我们来仔细看一下他的源代码

(二)、读源码

/**
 * Adapts a {@link Call} with response type {@code R} into the type of {@code T}. Instances are
 * created by {@linkplain Factory a factory} which is
 * {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into the {@link Retrofit}
 * instance.
 */
public interface CallAdapter<R, T> {
  /**
   * Returns the value type that this adapter uses when converting the HTTP response body to a Java
   * object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type
   * is used to prepare the {@code call} passed to {@code #adapt}.
   * <p>
   * Note: This is typically not the same type as the {@code returnType} provided to this call
   * adapter's factory.
   */
  Type responseType();

  /**
   * Returns an instance of {@code T} which delegates to {@code call}.
   * <p>
   * For example, given an instance for a hypothetical utility, {@code Async}, this instance would
   * return a new {@code Async<R>} which invoked {@code call} when run.
   * <pre><code>
   * @Override
   * public <R> Async<R> adapt(final Call<R> call) {
   *   return Async.create(new Callable<Response<R>>() {
   *     @Override
   *     public Response<R> call() throws Exception {
   *       return call.execute();
   *     }
   *   });
   * }
   * </code></pre>
   */
  T adapt(Call<R> call);

  /**
   * Creates {@link CallAdapter} instances based on the return type of {@linkplain
   * Retrofit#create(Class) the service interface} methods.
   */
  abstract class Factory {
    /**
     * Returns a call adapter for interface methods that return {@code returnType}, or null if it
     * cannot be handled by this factory.
     */
    public abstract CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

    /**
     * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
     * example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
     */
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    /**
     * Extract the raw class type from {@code type}. For example, the type representing
     * {@code List<? extends Runnable>} returns {@code List.class}.
     */
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}
1、老规矩先来看下 的注释:

将一个Call和他的响应类型R适配成T类型。实例由对应的Factory来创建,这个对应的Factory是通过Retrofit.Builder的addCallAdapterFactory(Factory)方法添加到Retrofit对象中的,在上述的过程中实现的初始化。

再来看下他两个方法的注释

2、看下他的Type responseType()方法的注释

返回此适配器将HTTP响应body转换为Java对象时使用的类型。 例如,"Call <Repo>"的响应类型是"Repo"。 此类型用于准备传递给"adapt"的"call"。 注意:这通常与提供给此呼叫适配器工厂的"returnType"不同。

3、看下他的 T adapt(Call<R> call)方法的注释

T 就是代表Retrofit里面Call的一个实例。后面的我实在是翻译不好,对不起大家了,其实说白了就是讲一个Retrofit的Call<T> 是适配成另外一个"Call"

4、看下他的子类 abstract class Factory

看上面的源码大家知道Factory是个子类,一般用Factory都是工厂模式。
老规矩看下他的 ***类**** 的注释,翻译一下就是

基于Retrofit的create方法的返回值创建CallAdapter实例。

看完上面的注释,大家应该发现了Retrofit的一个规律就是:retrofit定义了CallAdapter接口,内部有定义了一个Factory,工厂方法定义了如何生成CallAdapter,而CallAdapter又定义了如何拿到业务层定义的"Call"。所以他们的顺序如下:CallAdapter.Factory——>CallAdapter——>自定义的"Call"。

再来看下他的几个方法

四、Callback接口

这个接口就比较简单了,就不用大家思考了,Callback看字面意思就是回调,里面肯定一个是成功的回调,一个是错误的回调。直接读下源码

/**
 * Communicates responses from a server or offline requests. One and only one method will be
 * invoked in response to a given request.
 * <p>
 * Callback methods are executed using the {@link Retrofit} callback executor. When none is
 * specified, the following defaults are used:
 * <ul>
 * <li>Android: Callbacks are executed on the application's main (UI) thread.</li>
 * <li>JVM: Callbacks are executed on the background thread which performed the request.</li>
 * </ul>
 *
 * @param <T> Successful response body type.
 */
public interface Callback<T> {
  /**
   * Invoked for a received HTTP response.
   * <p>
   * Note: An HTTP response may still indicate an application-level failure such as a 404 or 500.
   * Call {@link Response#isSuccessful()} to determine if the response indicates success.
   */
  void onResponse(Call<T> call, Response<T> response);

  /**
   * Invoked when a network exception occurred talking to the server or when an unexpected
   * exception occurred creating the request or processing the response.
   */
  void onFailure(Call<T> call, Throwable t);
1、先看下 的注释

从服务器或离线请求的对应的响应(response)。 对应指定请求的,有且仅有一个方法与其对应。
由Retrofit的callback executor执行回调方法。当没有指定时,使用下面的默认值:
如果是 Android:回调在应用程序的主(UI)线程上执行,如果是JVM,则在执行请求的后台线程上执行回调。
泛型参数<T> 代表成功的响应类的类型

这个接口就两个方法,一个对应成功的回调,一个对应失败的回调

五、Converter接口

Converter我认为挺简单的,就是负责类型转换

(一)、思考

一个问题:

1、如果让你"设计"这个Converter接口你要怎么设计
————————分割线,思考上面的问题——————————
这个问题 我是这么想的

因为是给网络场景下的使用的,我的第一反应是写两个方法,一个方法是在请求的时候,写数据进行序列化的时候;还有一个就是在响应的时候, 读取数据进行反序列化的时候。

(二)、源码

/**
 * Convert objects to and from their representation in HTTP. Instances are created by {@linkplain
 * Factory a factory} which is {@linkplain Retrofit.Builder#addConverterFactory(Factory) installed}
 * into the {@link Retrofit} instance.
 */
public interface Converter<F, T> {
  T convert(F value) throws IOException;

  /** Creates {@link Converter} instances based on a type and target usage. */
  abstract class Factory {
    /**
     * Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for
     * response types such as {@code SimpleResponse} from a {@code Call<SimpleResponse>}
     * declaration.
     */
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }

    /**
     * Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for types
     * specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
     * values.
     */
    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }

    /**
     * Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for types
     * specified by {@link Field @Field}, {@link FieldMap @FieldMap} values,
     * {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
     * {@link Query @Query}, and {@link QueryMap @QueryMap} values.
     */
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
  }
}
1、看下类的注释

在HTTP请求中实现对象的转化。Converter这个类的实例由Factory创建。而这个Factory则由Retrofit.Builder的addConverterFactory()方法来进行初始化的

这个接口的抽象方法比较少,就一个

T convert(F value) throws IOException

不用注释,大家也知道把F 转化为T,这个接口是有两个参数的,我把F称为转入类型,T为转出类型,因为要把F转化为T。

哎 好像和我想象的不一样哎,那我们继续看下他的抽象类Factory

2、抽象类Factory

看名字就知道是个工厂类,肯定是通过这个工厂来产生Converter对象。

(1)、看下类的注释

基于类型和目标来创建一个Converter的实例

(2)、看下对应的三个方法的注释
(3)、总结

Retrofit 明显想的比我多,设计比我优雅,那我们来总结下这个接口

六、ExecutorCallAdapterFactory

上文讲解Platform中的静态内部类Android的defaultCallAdapterFactory方法里面返回的是一个ExecutorCallAdapterFactory的对象。那我们就在讲解下ExecutorCallAdapterFactory类

(一)、上源码

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

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }
  // get方法,创建并返回Android平台默认CallAdapter
  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
     //先判断原始类型是不是Call,这个Call是retrofit包下的Call
    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);
      }
    };
  }

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

      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 boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }
}

麻蛋,又是一个没有注释的类,不过通过源码我们知道这是一个final类,不能被继承。

首先这个ExecutorCallAdapterFactory类实现了CallAdapter.Factory,所以必然实现了CallAdapter.Factory接口的方法,我们来看下这个get方法内部的实现流程

ExecutorCallbackCall是个神马东西,原来ExecutorCallbackCall是ExecutorCallAdapterFactory的静态内部类,那么我们来分析一下ExecutorCallAdapterFactory类。

(二)、ExecutorCallbackCall类分析

1、上源码
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");

      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 boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }
2、看上面源码我们能得知如下内容:
3、所以总结一下ExecutorCallbackCall类

它实现了Call这个接口,Call我们前面说了,就是一个网络请求,然而我们这里看到这里并没有做实际请求,而是用了一个静态代理,通过这个delegate代理来实现call的请求,而在这里面做了一些其他的逻辑比如cancel逻辑,而实际上做这个请求还是交给了delegate。(其实OkHttpCall)

(三) ExecutorCallAdapterFactory 类总结

ExecutorCallAdapterFactory是CallAdapter.Factory的实现类,ExecutorCallAdapterFactory是将Call 适配成Call接口。但适配前和适配后的Call 还是不一样的,从enqueue方法中可以看到在callbackExecutor执行了回调,callbackExecutor上文已经介绍了,在Android平台就是UI主线程。

七、Platform类

为了方便大家后期更好的理解源码,我先给大家介绍一下Platform。这个Platform是个神马东东,字面理解是"平台",有啥神功疗效?
工欲善其事必先利其器,我们先来看下源码

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

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

  Executor defaultCallbackExecutor() {
    return null;
  }

  CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }

  boolean isDefaultMethod(Method method) {
    return false;
  }

  Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, Object... args)
      throws Throwable {
    throw new UnsupportedOperationException();
  }

  @IgnoreJRERequirement // Only classloaded and used on Java 8.
  static class Java8 extends Platform {
    @Override boolean isDefaultMethod(Method method) {
      return method.isDefault();
    }

    @Override Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
        Object... args) throws Throwable {
      // Because the service interface might not be public, we need to use a MethodHandle lookup
      // that ignores the visibility of the declaringClass.
      Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
      constructor.setAccessible(true);
      return constructor.newInstance(declaringClass, -1 /* trusted */)
          .unreflectSpecial(method, declaringClass)
          .bindTo(object)
          .invokeWithArguments(args);
    }
  }

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

这个类好坑啊,居然没有注释,不过通知字面的意思,我们

(一)、初始化

Platform 的初始化

  private static final Platform PLATFORM = findPlatform();
  static Platform get() {
    return PLATFORM;
  }
  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();
  }

Platform字面的意思就是平台。所以Platform其实就是一个父类,不同平台对应不同的实现子类。Android、Java 8 对应的是各种具体平台。可以看到,调用findPlatform()方法之后就回去判断对应的平台,具体实现的子类就是Android 和Java。

这里提一下我的小插曲,按照我之前分析okHttp的思路,okHttp里面也有Platform。所以我直接在Retrofit的包下找AndroidPlatform,结果发现没有,我就蒙圈了,后来才发现在Platform的内部类里面,汗.....

由于我们针对Android平台关于Java的具体设置,我就不讲解了,这里看下对应的Platform的内部类Anroid

(二)、Android

Android是Platform的静态内部类
代码很简介,如下:

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

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
  }

而Android类就两个方法,一个是defaultCallbackExecutor,另外一个是defaultCallAdapterFactory,从字面的意思我们可以知道,defaultCallbackExecutor()这个方法应该是返回的是默认的回调的线程池容器,defaultCallAdapterFactory()方法返回的是默认的请求适配工厂(CallAdapterFactory)。

那MainThreadExecutor是什么东西?原来MainThreadExecutor是Android的静态内部类。那我们来看下MainThreadExecutor这个类

(三)、MainThreadExecutor

看字面意思,我的理解是主线程的线程池。
来看下源码:

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

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

代码很简单,通过new Handler(Looper.getMainLooper())来获取一个主线程的Handler。然后在执行主线程的时候,调用的是主线程的handler的post方法。

ExecutorCallAdapterFactory 这个类 我们在下面讲解。

(四)、总结

Platform 其实就是一个"平台",定义了一些平台共有的方法,然后也针对不同的平台定义了一些不同的具体实现子类,比如各个不同平台根据不同环境来初始化不同的MainThreadExecutor。这里也可以看到,在初始化Platform之后,通过Platform得到的ExecutorCallAdapterFactory的工厂的Excecutor其实就是运行在主线程的Executor。

八 HttpException类

这个类比较简单,就不用想了,肯定肯定是Retrofit处理异常的的异常包装类,代码不多,直接上源码:

/** Exception for an unexpected, non-2xx HTTP response. */
public class HttpException extends Exception {
  private static String getMessage(Response<?> response) {
    if (response == null) throw new NullPointerException("response == null");
    return "HTTP " + response.code() + " " + response.message();
  }

  private final int code;
  private final String message;
  private final transient Response<?> response;

  public HttpException(Response<?> response) {
    super(getMessage(response));
    this.code = response.code();
    this.message = response.message();
    this.response = response;
  }

  /** HTTP status code. */
  public int code() {
    return code;
  }

  /** HTTP status message. */
  public String message() {
    return message;
  }

  /**
   * The full HTTP response. This may be null if the exception was serialized.
   */
  public Response<?> response() {
    return response;
  }
}

通过注释我们知道,这个HttpException主要是用来处理意外的、非2xx的响应异常
这个类就三个变量

最后他又定义了 静态方法getMessage(Response<?>),传入一个Response,返回一个拼接的String。

PS:

HttpException 里面的Response是Retrofit里面的Response,OkHttp里面也有一个Response。大家不要混淆了!

这个类比较简单,只能讲这么多了

九、面向接口编程

oop.png

面向接口编程

Interface-based programming, also known as interface-based architecture, is an architectural pattern for implementing modular programming at the component level in an object-oriented programming language which does not have a module system.

翻译一下:

面向接口编程,也被熟知为基于接口的设计,是一种基于组件级别的,面向对象语言的模块化编程设计实现。

说道面向接口不得不说面向对象,不过面向接口编程和面向对象编程实际上两个不同层级的概念。理论上说具有对象概念的程序设计都可以称之为面向对象编程,而面向接口编程则是从组件的级别来设计代码,认为地将抽象与实现分离。面向接口编程仅仅是面向对象编程的一种模块化实现形式而已。

(一)所谓的“接口”

面向接口编程中的"接口" 二字具体到Java语言中不仅仅是"interface"关键字这么简单。可以理解为接口是对具体实现的抽象。试想一下,团队协同以及代码健壮可维护性的需求日益增强的趋势下,通过暴露接口来提供服务本身是一件非常愉悦的事情。A需要调用B的服务,A却不需要去仔细阅读B写的代码,通过接口文档就可以看出对应业务的方法和参数类型,进而使用RMI或者RPC等相关技术实现模块化的调用。而这一切本身就是相面接口编程。

换一种角度,我们怎么定义接口:“接口泛指实体把自己提供给外界的一种抽象化物,用以由内部操作分离出外部沟通方法,使其能被修改内部而不影响外界其他实体与其交互的方式”,话句话说,在我们程序的世界里,接口的作用就是用于定义一个或一组规则,实现对应接口的实体需要遵循对应的这些规则。也可以说是对“同类事物”的抽象表示,而“同类事物”的界定就看是否实现了同一个接口,譬如一个Animal接口和NightWorking接口,公鸡实现了Animal接口,猫头鹰实现了Animal接口和NightWorking接口,还有一个实现了NightWorking的接口的酒吧,在Animal的范畴下,我们可以称公鸡和猫头鹰是同类事物,但是在NightWorking的范畴下,我们可以把我们可以称猫头鹰和酒吧是同类事物。有点恐怖吧

很多刚刚接触面向接口编程的Java开发者会认为,既然面向接口编程,那么就把实现抽象为接口就是优良的设计。但实际上他们混淆了Java中的interface和面向接口编程的"接口的"概念。实际上,interface、abstract class以及普通的class 都能成为所谓的接口,甚至 abstract class的功能可以更加强大。那么interface和abstract class 区别是什么?

(二)、abstract class和interface的区别:

abstract class和interface的区别在于,interface约定的是务必实现的方法,强调的是规则的制定。abstract class则是在抽象的同时允许提供一些默认的行为,以达到代码复用的效果。例如一定一些基础、初始化以及类回收方法等。另外,还有一个常识性的区别,一个实现类(相对于抽象而言)可以实现多个interface,而只能继承一个abstract class,在代码设计的过程中务必注意。

(三)、面向接口的优势:

(四)、 面向接口的编程方式

上一篇下一篇

猜你喜欢

热点阅读