美文网首页
retrofit 源码优秀代码功能点学习

retrofit 源码优秀代码功能点学习

作者: Android小悟空 | 来源:发表于2021-03-08 15:13 被阅读0次

    @Nullable和@Nonnull的使用

    在编写方法时,入参、返回值,记得要用@Nullable和@Nonnull修饰,来达到提醒调用方的目的(kotlin应该不用)

    泛型的大量使用

    一个好的架构,一定是可以兼容各种数据类型,各种场景的,所以通过泛型可以很好的解决这些问题,所以泛型的使用是架构设计的核心

    public interface TypeQualifierValidator<A extends Annotation> {
        public @Nonnull
        When forConstantValue(@Nonnull A annotation, Object value);
    }
    
    public final class Response<T> {
      /** Create a synthetic successful response with {@code body} as the deserialized body. */
      public static <T> Response<T> success(@Nullable T body) {
        return success(
            body,
            new okhttp3.Response.Builder() //
                .code(200)
                .message("OK")
                .protocol(Protocol.HTTP_1_1)
                .request(new Request.Builder().url("http://localhost/").build())
                .build());
      }
    }  
    
    public <T> T create(final Class<T> service) {
        validateServiceInterface(service);
    }
    
    private void validateServiceInterface(Class<?> service) {
        if (!service.isInterface()) {
          throw new IllegalArgumentException("API declarations must be interfaces.");
        }
        
        Deque<Class<?>> check = new ArrayDeque<>(1);
    }
    

    final class

    retrofit 源码中有大量的类都是使用final来修饰的
    final修饰class有以下特点 :

    • 当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。
    • 所以说,当开发时,如果写的类是非Activity、Fragment、View、Service等非android类时,应尽量考虑final class的情况

    String类就是一个final类:

    public final class String implements Serializable, Comparable<String>, CharSequence {
        ...
    }
    

    final 修饰方法时:

    • 即父类的final方法是不能被子类所覆盖的,也就是说子类是不能够存在和父类一模一样的方法的
    • 不能被重写
    public class B extends A {
      public void getName() {
    
      }
    }
    
    class A {
      public final void getName() {
    
      }
    }
    
    当A类的getName是被final修饰时,如果B extends A ,那么不能重写getName方法,会直接报错:
    getName()' cannot override 'getName()' in 'retrofit2.A'; overridden method is final
    

    final 修饰变量时:

    • final成员变量表示常量,只能被赋值一次,赋值后值不再改变。

    static final class

    public static final class Builder {}
    

    build模式和工厂模式(工厂、抽象工厂)的使用

    <? extends Annotation>和<?, ?>的使用

    @Override
    public Class<? extends Annotation> annotationType() {
        return SkipCallbackExecutor.class;
    }
    

    abstract class(抽象类)的使用

    abstract class ServiceMethod<T> {
      static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    
        Type returnType = method.getGenericReturnType();
        if (Utils.hasUnresolvableType(returnType)) {
          throw methodError(
              method,
              "Method return type must not include a type variable or wildcard: %s",
              returnType);
        }
        if (returnType == void.class) {
          throw methodError(method, "Service methods cannot return void.");
        }
    
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
      }
    
      abstract @Nullable T invoke(Object[] args);
    }
    

    使用String字符串拼接时,要用StringBuilder

    StringBuilder builder =
        new StringBuilder("Could not locate call adapter for ").append(returnType).append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
    

    StringBuilder效率高,线程不安全
    StringBuffer效率低,线程安全

    Objects.requireNonNull(type, "type == null");的使用

    Objects.requireNonNull(type, "type == null");
    Objects.requireNonNull(parameterAnnotations, "parameterAnnotations == null");
    Objects.requireNonNull(methodAnnotations, "methodAnnotations == null");
    
    底层(sdk组件)字段校验可以使用这样的方式,来避免调用方传一些错误字段,但是上层业务不能这样写,要处理异常而不是抛出
    

    for循环中创建count对象

    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter.Factory factory = converterFactories.get(i);
      Converter<?, RequestBody> converter =
          factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<T, RequestBody>) converter;
      }
    }
    
    for循环中,使用count = converterFactories.size()的方法,直接创建了count对象
    

    反射reflect中Type的意义和使用

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

    List作为返回值,而不是ArrayList等

    public List<Converter.Factory> converterFactories() {
    return converterFactories;
    }
    

    动态代理的使用

    public <T> T create(final Class<T> service) {
        validateServiceInterface(service);
        return (T)
            Proxy.newProxyInstance(
                service.getClassLoader(),
                new Class<?>[] {service},
                new InvocationHandler() {
                  private final Platform platform = Platform.get();
                  private final Object[] emptyArgs = new Object[0];
    
                  @Override
                  public @Nullable 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);
                    }
                    args = args != null ? args : emptyArgs;
                    return platform.isDefaultMethod(method)
                        ? platform.invokeDefaultMethod(method, service, proxy, args)
                        : loadServiceMethod(method).invoke(args);
                  }
                });
      }
    

    用线程池Executor而不是直接使用new Thread()

    final @Nullable Executor callbackExecutor;
    

    package-info.java的使用

    @retrofit2.internal.EverythingIsNonNull
    package retrofit2;
    
    package-info.java是一个特殊的类,可以对整个包做操作。
    retrofit中使用package-info.java为retrofit2包中的每一个类都添加了注释@retrofit2.internal.EverythingIsNonNull
    

    kotlin中泛型、内联函数、扩展函数的用法:

    
    inline fun <reified T> Retrofit.create(): T = create(T::class.java)
    

    相关文章

      网友评论

          本文标题:retrofit 源码优秀代码功能点学习

          本文链接:https://www.haomeiwen.com/subject/iobpqltx.html