Android

Retrofit

2018-03-06  本文已影响0人  gczxbb

Retrofit设计模式

动态代理,装饰模式,建造者模式,抽象工厂模式,适配器模式

建造者模式创建Retrofit对象。

Retrofit retrofit = new Retrofit.Builder().baseUrl(builder.getHostIp())
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)//Retrofit客户端设置为OkHttpClient
                .build();

1.动态代理

Retrofit#create方法负责创建一个动态代理对象。

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() {
            //该对象传入$Proxy0的构造方法中
            private final Platform platform = Platform.get();
            @Override 
            public Object invoke(Object proxy, Method method, Object... args) 
                        throws Throwable {
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                if (platform.isDefaultMethod(method)) {
                    return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                ServiceMethod serviceMethod = loadServiceMethod(method);
                OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.callAdapter.adapt(okHttpCall);
              }
        });
}

利用注解来描述一个Http请求,抽象成Java接口,然后利用反射和动态代理创建service代理对象。Class<?>[]接口数组只有一个元素service。
service服务API

@POST("app.do?")
Call<ServerTimeResponse> getTime(@Query("app_code") String appCode,
                                 @Query("pattern") String pattern);

利用代理对象访问service接口API的interface方法,最后都会调用InvocationHandler#invoke方法

生成代理对象

通过抽象接口生成代理。
Proxy#newProxyInstance方法。

public static Object newProxyInstance(ClassLoader loader, 
                Class<?>[] interfaces,
                InvocationHandler invocationHandler)
                throws IllegalArgumentException {
    if (invocationHandler == null) {
        throw new NullPointerException("invocationHandler == null");
    }
    Exception cause;
    try {
        return getProxyClass(loader, interfaces)
                .getConstructor(InvocationHandler.class)
                .newInstance(invocationHandler);
    } catch (NoSuchMethodException e) {
        ...
    } catch (IllegalAccessException e) {
    } catch (InstantiationException e) {
    } catch (InvocationTargetException e) {
    }
}

触发getProxyClass方法,返回Class<?>对象,然后newInstance方法创建实例。
Proxy#getProxyClass方法。

public static Class<?> getProxyClass(ClassLoader loader, 
                    Class<?>... interfaces)
                    throws IllegalArgumentException {
    final List<Class<?>> interfaceList = 
                    new ArrayList<Class<?>>(interfaces.length);
    ...
    synchronized (loader.proxyCache) {
        Class<?> proxy = loader.proxyCache.get(interfaceList);
        if (proxy != null) {
            return proxy;
        }
    }
    ...
    List<Method> methods = getMethods(interfaces);
    Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
    ...

    String baseName = commonPackageName != null && !commonPackageName.isEmpty()
                ? commonPackageName + ".$Proxy"
                : "$Proxy";
    Class<?> result;
    synchronized (loader.proxyCache) {
        result = loader.proxyCache.get(interfaceList);
        if (result == null) {
            String name = baseName + nextClassNameIndex++;
            result = generateProxy(name, interfaces, loader, methodsArray, exceptionsArray);
            loader.proxyCache.put(interfaceList, result);
        }
    }
    return result
}

1:getProxyClass方法根据interfaces数组,在缓存中查找代理类Class<?> proxy,若找到返回。
2:查找interfaces接口数组的方法,Method排序,增加equal,toString,hashCode三个方法。generateProxy是native方法,根据name,interfaces数组和Methods生成代理类$Proxy0
3:代理类Class<?>继承Proxy,且实现了interface的方法,具有Proxy与interface两重属性,最后将Class<?>存储在proxyCache缓存中。
4:$Proxy0创建完成后,查找$Proxy0中有InvocationHandler参数的构造器Constructor,利用newInstance方法创建$Proxy0对象。

创建的代理对象是虚拟机运行时动态生成的一个对象。命名方式以$开头,Proxy和数字。

protected Proxy(InvocationHandler h) {
    this.h = h;
}

在$Proxy0构造方法中传入了一个InvocationHandler对象,就是在Retrofit#create中new的那个对象InvocationHandler

用户利用$Proxy0中的interface方法实现Http访问。

路由到InvocationHandler#invoke方法

$Proxy0类生成的interface方法触发super.h.invoke方法,所有的方法都会进入InvocationHandler#invoke方法($Proxy0类反编译可查看)。
在Retrofit#create实现,入参代理对象,interface方法的Method和args参数,解析成Call返回。

动态代理这一套固定的代码可以无侵入的扩展各种Service服务API,基本逻辑是创建一个具有API接口属性的Proxy子类,实现API的方法触发引入了InvocationHandler对象invoke。


2.适配对接okhttp3

Retrofit的对接okhttp3

ServiceMethod对象

private final Map<Method, ServiceMethod> serviceMethodCache = 
                    new LinkedHashMap<>();

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

每个service接口服务方法创建ServiceMethod对象,存储在一个serviceMethodCache缓存中,防止每次调用服务方法都创建一个对象,ServiceMethod负责解析Method。
回到InvocationHandler#invoke方法,返回的Object是Call<?>。

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

CallAdapter<?>适配器与工厂

ServiceMethod的Call适配器CallAdapter<?>接口。

public interface CallAdapter<T> {
    Type responseType();

    <R> T adapt(Call<R> call);
    //创建CallAdapter的工厂
    abstract class Factory {
        public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,
                    Retrofit retrofit);

        protected static Type getParameterUpperBound(int index, ParameterizedType type) {
            return Utils.getParameterUpperBound(index, type);
        }

        protected static Class<?> getRawType(Type type) {
            return Utils.getRawType(type);
        }
    }
}

Factory工厂创建适配器,Retrofit#nextCallAdapter方法。

public CallAdapter<?> nextCallAdapter(...) {
    ..
    CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
    ...
}

Retrofit工厂初始化

Retrofit build()方法

List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

默认工厂ExecutorCallAdapterFactory,继承CallAdapter.Factory,创建CallAdapter,适配的Call是ExecutorCallbackCall。
ExecutorCallAdapterFactory#get方法,创建一个CallAdapter,adapt适配方法。

@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    ...
    return new CallAdapter<Call<?>>() {
        @Override
        public Type responseType() {
            return responseType;
        }

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

ExecutorCallbackCall实现Retfofit#Call接口,adapt的入参是OkHttpCall ,delegate委派模式
ExecutorCallbackCall与OkHttpCall都实现Retfofit#Call接口,service服务方法返回的Call都是ExecutorCallbackCall对象,真正调用的是OkHttpCall

ExecutorCallbackCall分析

ExecutorCallbackCall实现Retrofit#Call接口,方法委派给OkHttpCall。

@Override 
public void enqueue(final Callback<T> callback) {//Retrofit#Callback
    ..//delegate是OkHttpCall。
    delegate.enqueue(new Callback<T>() {//Retrofit#Callback
        @Override public void onResponse(Call<T> call, final Response<T> response) {
            callbackExecutor.execute(new Runnable() {
                @Override public void run() {
                    if (delegate.isCanceled()) {
                        callback.onFailure(...);
                    } else {
                        //callback是用户传入
                        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方法创建一个Callback,触发onResponse方法时,callbackExecutor线程池执行任务,callbackExecutor是MainThreadExecutor。

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

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

MainThreadExecutor#execute将Runnable发送到主线程消息队列,进一步封装CallBack的主要目的是将请求回调代码路由到主线程
OkHttpCall#enqueue请求的Callback,就是封装用户传入Callback的对象。

OkHttpCall分析

OkHttpCall实现Retrofit#Call接口,封装okhttp3框架的请求对象,实现方法对接,主要方法包括enqueue,execute,request
OkHttpCall#enqueue方法,实现okhttp3异步请求。

@Override //Retrofit#Call的方法
public void enqueue(final Callback<T> callback) {//Retrofit的Callback
    okhttp3.Call call;
    Throwable failure;

    call = rawCall;//OkHttp的Call
    failure = creationFailure;
    ...
    if (canceled) {
        call.cancel();
    }

    call.enqueue(new okhttp3.Callback() {//okhttp3异步请求
        @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) {
            }
        }
      ...
      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
        }
      }
    });
}

ServiceMethod#toResponse方法。

T toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
}
private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);//解析参数,生产okHttp3#Request
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);//通过工厂创建rawCall
    ...
    return call;
}

ServiceMethod#toRequest方法将Method的参数arg转换成一个Http协议的okHttp3#Request请求,arg就是service服务方法的入参。根据Request,okhttp3.Call#Factory工厂负责创建OKhttp3#Call。
创建okhttp3.Call#Factory工厂,Retrofit建造者中的client方法传入OkHttpClient,OKhttpClinent继承okhttp3.Call.Factory

public Builder client(OkHttpClient client) {
    return callFactory(checkNotNull(client, "client == null"));
}

Converter转换

GsonConverterFactory实现Converter.Factory接口,Converter.Factory抽象工厂负责生产三类Converter。ResponseBody,RequestBody,String。

public interface Converter<F, T> {
  T convert(F value) throws IOException;
  //创建Converter的抽象工厂
  abstract class Factory {

    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }

    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }

    public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
  }
}

GsonConverterFactory工厂创建Converter<ResponseBody, T> responseConverter,负责转换ResponseBody对象,转换成用户自己定义的实体对象,即service接口方法返回Call<?>中的泛型。然后创建一个Retrofit#Response封装实体。工厂的抽象方法是固定的,子类工厂提供不同的具体实现。

其他扩展,如RxJava,基于Retrofit接口设计,在创建对象时可使用不同的Convert和CallAdapter工厂,耦合性低,实现插件化。

Retrofit retrofit = new Retrofit.Builder().baseUrl(AppEnvConstants.http_ip)
    .addConverterFactory(ProtoConverterFactory.create())//不同的Converter工厂
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//不同的CallAdapter工厂
    .build();

总结:Retrofit利用动态代理,根据一组网络请求的接口服务生成一个代理对象,为每一个接口方法生成一个ServiceMethod,主要负责解析接口方法,包括注解与参数等,注解解析成Http访问类型POST/GET等,参数封装成Request。
适配器CallAdapter与抽象工厂设计使Retrofit和okhttp3无缝对接。


任重而道远

上一篇下一篇

猜你喜欢

热点阅读