仅实现Retrofit中的注解和动态代理
大概流程:
1.通过动态代理实例化接口
2.每调用一个方法都会调用到动态代理里面的 InvocationHandler,所以通过这个方法可以解析方法上面的注解及值,参数注解及值。
3.创建一个HashMap键是Method 值是ServiceMehtod(保存注解信息的类) 来保存在内存中,再次访问就可以省去解析时间
直接上实现代码
Api api;
CustomRetrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
//自定义的用法
retrofit = new CustomRetrofit.Builder().baseUrl(url).build();
api = retrofit.create(Api.class);
//Retrofit 的用法
Retrofit retrofit1 = new Retrofit.Builder().baseUrl(url).build();
Api api1 = retrofit1.create(Api.class);
}
public void post(View view) {
Call call = api.postWeather(city,key);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.e(TAG, "post onFailure: "+e.getMessage() );
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()){
Log.e(TAG, "post onResponse: "+response.body().string() );
}
}
});
}
public void get(View view) {
Call call = api.getWeather(city,key);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.e(TAG, "get onFailure: "+e.getMessage() );
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()){
Log.e(TAG, "get onResponse: "+response.body().string() );
}
}
});
}
现在看下自定义类CustomRetrofit中的实现
package com.test.retrofit;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import okhttp3.Call;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
public class CustomRetrofit {
protected HttpUrl baseUrl;
protected Call.Factory callFactory;
private HashMap<Method,ServiceMethod> serviceMethodCache = new HashMap<>();
private CustomRetrofit(HttpUrl baseUrl,Call.Factory callFactory){
this.baseUrl = baseUrl;
this.callFactory = callFactory;
}
//使用动态代理,把接口生成一个class,然后实例化赋值给泛型接口T(简单来讲就是给接口实例化了)
public <T> T create(Class<T> service){
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// args是方法的参数
//解析这个method 上所有的注解信息
ServiceMethod serviceMethod = loadServiceMethod(method);
return serviceMethod.invoke(args);
}
});
}
private ServiceMethod loadServiceMethod(Method method) {
//如果内存中有直接取内存中了,不用重复分析注解信息
ServiceMethod serviceMethod = serviceMethodCache.get(method);
if(serviceMethod != null)
return serviceMethod;
//加锁,防止同步重复创建值 类似单例双重锁机制
synchronized (serviceMethodCache){
serviceMethod = serviceMethodCache.get(method);
if(serviceMethod == null){
serviceMethod = new ServiceMethod.Builder(this,method).build();
//添加进内存中
serviceMethodCache.put(method,serviceMethod);
}
}
return serviceMethod;
}
public static class Builder{
private HttpUrl baseUrl;
private Call.Factory callFactory;// = new OkHttpClient();
public Builder(){
}
public Builder baseUrl(String url){
baseUrl = HttpUrl.get(url);
return this;
}
public Builder client(Call.Factory factory ){
this.callFactory = factory;
return this;
}
public CustomRetrofit build(){
if (baseUrl == null)
throw new RuntimeException("URL不能为空");
if(callFactory == null)
callFactory = new OkHttpClient();
return new CustomRetrofit(baseUrl,callFactory);
}
}
}
再看下ServiceMethod.java类
package com.test.retrofit;
import com.example.retrofit.annotation.Field;
import com.example.retrofit.annotation.GET;
import com.example.retrofit.annotation.POST;
import com.example.retrofit.annotation.Query;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request;
/**
* 记录请求方法的成员 请求方式 值等信息
*/
public class ServiceMethod {
//POST请求,要添加的请求体
private FormBody.Builder formBuilder;
//GET请求直接拼接在url里面
private HttpUrl.Builder urlBuilder;
//请求服务端得请求类型 POST GET
private String serviceMethodRequestType;
//Retrofit传过来的http信息
private HttpUrl baseUrl;
//注解上面的接口字符串
private String relativeUrl;
//是否有请求体/POST才有
private boolean hasBody;
//参数变量的值
private ParameterHandler[] parameterHandlers;
private Call.Factory callFactory;
private ServiceMethod(Builder builder){
this.baseUrl = builder.retrofit.baseUrl;
this.callFactory = builder.retrofit.callFactory;
this.relativeUrl = builder.relativeUrl;
this.parameterHandlers = builder.parameterHandlers;
this.serviceMethodRequestType = builder.serviceMethodRequestType;
this.hasBody = builder.hasBody;
if (hasBody){
formBuilder = new FormBody.Builder();
}
}
public Object invoke(Object[] args) {
//往body里面赋值
for (int i = 0; i < parameterHandlers.length; i++) {
parameterHandlers[i].apply(this,args[i].toString());
}
HttpUrl url;
if (urlBuilder == null){
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
url = urlBuilder.build();
//如果有请求体的话,添加请求体
FormBody formBody = null;
if(formBuilder != null){
formBody = formBuilder.build();
}
//创建请求
Request request = new Request.Builder()
.url(url)
.method(serviceMethodRequestType,formBody)
.build();
//返回Call
return callFactory.newCall(request);
}
//GET请求 拼接URL
protected void addQueryData(String key,String value){
if (urlBuilder == null){
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
urlBuilder.addQueryParameter(key,value);
}
//POST请求 添加请求体
protected void addFieldData(String key,String value){
formBuilder.add(key,value);
}
public static class Builder{
//CustomRetrofit对象
private CustomRetrofit retrofit;
//请求服务端得请求类型 POST GET
private String serviceMethodRequestType;
//获取方法上的注解
private Annotation[] methodAnnotations = new Annotation[]{};
//获取方法成员的注解
private Annotation[][] parameterAnnotations = new Annotation[][]{};
//是否有请求体
private boolean hasBody;
//注解上面的url
private String relativeUrl;
//成员变量的值
private ParameterHandler[] parameterHandlers;
public Builder(CustomRetrofit retrofit, Method method){
this.retrofit = retrofit;
//获取方法上面的注解
this.methodAnnotations = method.getDeclaredAnnotations();
//获取方法参数上的注解 可能一个参数可能有多个注解,所以是二元数组
this.parameterAnnotations = method.getParameterAnnotations();
}
public ServiceMethod build(){
//获取请求类型
for (Annotation methodAnnotation : methodAnnotations) {
//判断方法上的注解是上面类型这里只举例两种
if(methodAnnotation instanceof POST){
this.hasBody = true;
//获取注解的值 也就是POST("api/getData")中的 api/getData
this.relativeUrl = ((POST) methodAnnotation).value();
this.serviceMethodRequestType = "POST";
}
if(methodAnnotation instanceof GET){
this.hasBody = false;
//获取注解的值 也就是GET("api/getData")中的 api/getData
this.relativeUrl = ((GET) methodAnnotation).value();
this.serviceMethodRequestType = "GET";
}
}
int length = parameterAnnotations.length;
//保存参数的类
parameterHandlers = new ParameterHandler[length];
for (int i = 0; i < length; i++) {
Annotation[] annotations = parameterAnnotations[i];
for (Annotation annotation : annotations) {
//POST请求
if (annotation instanceof Field){
String key = ((Field) annotation).value();
parameterHandlers[i] = new ParameterHandler.FieldParameterHandler(key);
}
//GET请求
if(annotation instanceof Query){
String key = ((Query) annotation).value();
parameterHandlers[i] = new ParameterHandler.QueryParameterHandler(key);
}
}
}
return new ServiceMethod(this);
}
}
}
剩下的就是保存参数的ParameterHandler
package com.test.retrofit;
public abstract class ParameterHandler {
public abstract void apply(ServiceMethod serviceMethod,String value);
public static class QueryParameterHandler extends ParameterHandler{
private String key;
public QueryParameterHandler(String key){
this.key = key;
}
@Override
public void apply(ServiceMethod serviceMethod, String value) {
serviceMethod.addQueryData(key,value);
}
}
public static class FieldParameterHandler extends ParameterHandler{
private String key;
public FieldParameterHandler(String key) {
this.key = key;
}
@Override
public void apply(ServiceMethod serviceMethod, String value) {
serviceMethod.addFieldData(key,value);
}
}
}