Retrofit中使用到了很多設計模式,其核心的模式是代理模式,因爲Retrofit 不是一個網絡框架,而是一個對網絡框架進行封裝的工具,利用註解將請求的接口以java的接口形式展現,其請求的核心還是Okhttp,它的幾個核心的功能:轉換註解、解析請求的參數、請求、將請求的結果適配爲我們想要的結果等重要功能都是在動態代理中完成的
代理模式
在java代碼中,代理模式分爲靜態代理和動態代理
靜態代理
代理類通過實現與目標對象相同的接口,並在類中維護一個代理對象,通過構造函數實例化目標對象,保存給代理對象,在接下來的執行中代理對象實現接口方法,在這個方法中攔截,添加或者移除要修改的功能
看代碼
/**
* 共同的接口
*/
interface IProxyInterface {
fun method()
}
/**
* 目標對象
*/
class TargetObject : IProxyInterface {
override fun method() {
println("這裏是我原本要進行的操作")
}
}
/**
* 代理類
*/
class ProxyHelper(var iProxyInterface: IProxyInterface) : IProxyInterface {
override fun method() {
//再次做攔截之前的操作
iProxyInterface.method()
//再次做攔截之後的操作
}
}
- 優點:能完成我們在開發中大的代碼塊或依賴中的模塊功能的修改和擴展
- 缺點:自己寫代理類 增加了類文件,並且在接口發生改變時,代理類也需要改變
動態代理
既然靜態代理存在很明顯的缺點,那看一下動態代理,當然動態代理不需要自己實現代理類
動態代理類我們實現java提供的InvocationHandler類來實現,
看代碼
/**
* 動態代理類對象
*
*/
class DynamicProxyHandler(var any: Any) :InvocationHandler {
override fun invoke(proxy: Any, method: Method, args: Array<out Any>): Any {
//操作前
val result = method.invoke(proxy, args)
//操作後
return result
}
}
/**
*測試類
**/
object Main {
@JvmStatic
fun main(args: Array<String>) {
// ProxyHelper(TargetObject()).method()
val iProxyInterface = TargetObject()
val proxyInterface = Proxy.newProxyInstance(
IProxyInterface::class.java.classLoader,
arrayOf<Class<*>>(IProxyInterface::class.java), DynamicProxyHandler(iProxyInterface)
) as IProxyInterface
proxyInterface.method()
}
}
- Proxy.newProxyInstance三個參數的說明:
- ClassLoader :指定當前目標對象使用的類加載器,獲取加載器的方法是固定的
- Class<?>[] interfaces:指定目標對象實現的接口的類型,使用泛型方式確認類型
- InvocationHandler:執行目標對象的方法時通過回調invoke 方法完成操作
- 優點:不需要手動實現代理類
- 缺點:代理對象不需要實現接口但是目標對象一定要實現接口,
Retrofit 使用的就是動態代理
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
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.adapt(okHttpCall);
}
});
}