大家都说retrofit的经典之处就在于动态代理+注释,于是我专门去了解了动态代理和注解。下面开始我的猜想,retrofit的源码太复杂了我看不懂。
1、利用注释创建3个retrofit中的常见自定义注释
FormUrlEncoded.class
@Documented //标记这些注释是否包含在用户文档中
@Target({ElementType.METHOD})//注释用在哪里 方法
@Retention(RetentionPolicy.RUNTIME)//注释怎么保存 RUNTIME*运行时
public @interface FormUrlEncoded {
}
POST.class
@Documented //文档
@Target({ElementType.METHOD})//方法
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface POST {
String value() default "";
}
FieldMap.class
@Documented //文档
@Target({ElementType.PARAMETER})//参数
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface FieldMap {
boolean encoded() default false;
}
2、创建一个接口类来使用上门的注释,模拟开发中的请求接口定义
PayService.class
interface PayService {
/**
* 获取支付配置
*/
@FormUrlEncoded
@POST("appsdk/Sdk/GetPayment")
fun getPayConfig(@FieldMap body: MutableMap<String, Any>): Any
/**
* 进行支付
*/
@FormUrlEncoded
@POST("appsdk/Sdk/InternalSubmitOrder")
fun pay(@FieldMap body: MutableMap<String, Any>): Any
}
3、创建动态代理类,并获取对应函数中的注解信息
ServiceProxy.class
class ServiceProxy : InvocationHandler {
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
//获取函数的注释
if (method?.isAnnotationPresent(FormUrlEncoded::class.java) == true) {
println("函数有 FormUrlEncoded 注释")
}
if (method?.isAnnotationPresent(POST::class.java) == true) {
var annotation = method.getAnnotation(POST::class.java)
println("函数有 POST 注释 Value:" + annotation.value)
}
method?.apply {
var parameterAnnotations = parameterAnnotations
parameterAnnotations.forEach {
it.forEach { annotation ->
println(annotation)
if (annotation.annotationClass.simpleName == FieldMap::class.java.simpleName) {
println("参数上有 FieldMap 注释")
}
}
}
}
return ""//获取到需要的信息之后,完全可以组合成okhttp请求需要的各种参数
}
public fun <T> getServiceProxy(clz: Class<T>): T {
return Proxy.newProxyInstance(clz.classLoader, arrayOf(clz), this) as T
}
}
4、创建一个测试类,来看看能否获取到我们想要的信息
Test.kt
object Test {
@JvmStatic
fun main(args: Array<String>) {
val map = mutableMapOf<String, Any>(
"amount" to "",
"billno" to ""
)
ServiceProxy().getServiceProxy(PayService::class.java).let {
it.getPayConfig(map)
it.pay(map)
}
}
}
运行结果:
zhushi.jpg
既然能获取到注释的信息,那么我想我们就能利用代理的特效添加后置操作来请求okhttp了。