Retrofit是一个Restful的HTTP网络 请求框架的封装,网络请求的工作本质是由OkHttp完成, 而Retrofit仅负责完了请求和接口的封装.
在Retrofit底层其实运用了反射,注解,动态代理等技术,网络工作的完成,完全是由okhttp3.Call.Factory,经过源码分析, Factory只是一个接口,他只有唯一实现类,那就是我们熟悉的OkHttpClient,一般我们通过OkHttpClient完成网络参数的配置,例如请求超时时间等等...
在这里我们来模仿一个简单的Retrofit,有利于后面研究Retrofit和OkHttp源码.其中不包含converterFactories,callAdapterFactories等功能,
image.png
老规矩,先上效果图.
File: WeatherApi.java
import com.zyang.simpleretrofit.retrofit.annotaion.Field;
import com.zyang.simpleretrofit.retrofit.annotaion.GET;
import com.zyang.simpleretrofit.retrofit.annotaion.POST;
import com.zyang.simpleretrofit.retrofit.annotaion.Query;
import okhttp3.Call;
public interface WeatherApi {
@POST("/v3/weather/watherInfo")
Call postWeather(@Field("city")String city, @Field("key")String key);
@GET("/v3/weather/watherInfo")
Call getWeather(@Query("city") String city, @Query("key")String key);
}
ZyangRetrofit zyangRetrofit = new ZyangRetrofit.Builder()
.baseUrl("https://restapi.amap.com")
.build();
weatherApi = zyangRetrofit.create(WeatherApi.class);
okhttp3.Call call = weatherApi.getWeather("110101", "ae6c53e2186f33bbf240a12d80672d1b");
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onResponse: onFailure"+e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG, "onResponse: get: "+response.body().string());
response.close();
}
});
接下来就是框架的编写了.
1,导入okHttp相关资源包,不是Retrofit资源包
implementation 'com.squareup.okhttp3:okhttp:3.14.7'
2,编写Annotaion(注解)Field,GET,POST,Query.关于注解的知识大家可以看java注解这篇文章.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Field {
String value() ;
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Query {
String value();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GET {
String value() default "";
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface POST {
String value() default "";
}
3,编写ZyangRetrofit 类里面的createa()方法.在createa方法里面采用的是动态代理,主要职责是通过我们自己定义的WatherApi接口,动态创建创建WatherApi的代理对象,其实就是实现WatherApi接口的类.
//通过动态代理构建service接口的代理对象.
public <T> T create(final 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 {
ServiceMethod serviceMethod = loadServiceMethod(method);
return serviceMethod.invoke(args);
}
});
}
4,通过动态代理的InvocationHandler()接口中的invoke方法,去返回我们代理的对象. 首先编写ServiceMethod类.在ServiceMethod类主要是通过反射去解析接口方法和方法参数上面的注解,然后构建网络请求的环境. 最终通过OkHttp去完成网络请求的动作.
import com.zyang.simpleretrofit.retrofit.annotaion.Field;
import com.zyang.simpleretrofit.retrofit.annotaion.GET;
import com.zyang.simpleretrofit.retrofit.annotaion.POST;
import com.zyang.simpleretrofit.retrofit.annotaion.Query;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request;
/**
*/
public class ServiceMethod {
private final okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private String httpMethod;
private final String relativeUrl;
private FormBody.Builder formBuild;
private HttpUrl.Builder urlBuilder;
private final ParameterHandler[] parameterHandlers;
public ServiceMethod(Builder builder) {
callFactory = builder.zyangRetrofit.callFactory;
baseUrl = builder.zyangRetrofit.baseUrl;
httpMethod = builder.httpMethod;
relativeUrl = builder.relativeUrl;
parameterHandlers = builder.parameterHandlers;
if (builder.hashBody){
formBuild = new FormBody.Builder();
} // 到这里构建已经完成差不多了
}
public Object invoke(Object[] args) {
/*
1,处理请求的地址与参数
*/
for (int i = 0; i < parameterHandlers.length; i++) {
ParameterHandler handlers = parameterHandlers[i];
handlers.apply(this,args[i].toString());
}
HttpUrl url;
//获取最终请求地址
if (urlBuilder == null) {
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
url = urlBuilder.build();
FormBody formBody = null;
if (formBuild != null){
formBody = formBuild.build();
}
Request request = new Request.Builder()
.url(url).method(httpMethod,formBody).build();
return callFactory.newCall(request);
}
public void addQueryParameterHandler(String key, String value) {
if (urlBuilder == null) {
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
urlBuilder.addQueryParameter(key,value);
}
public void addFiledParameter(String key, String value) {
formBuild.add(key,value);
}
public static final class Builder {
private final ZyangRetrofit zyangRetrofit;
private final Annotation[] methodAnnotations;
private final Annotation[][] parameterAnnotations;
private String httpMethod;
private String relativeUrl;
private boolean hashBody;
private ParameterHandler[] parameterHandlers;
public Builder(ZyangRetrofit zyangRetrofit, Method method) {
this.zyangRetrofit = zyangRetrofit;
//获取方法上所有的注解
methodAnnotations = method.getAnnotations();
// 获取方法参数的所有的注解(一个参数可以有多个注解, 一个方法又会有多个参数)
parameterAnnotations = method.getParameterAnnotations();
}
public ServiceMethod build(){
/*
todo:1,解析方法上的所有注解, 只处理POST与GET
*/
for (Annotation methodAnnotation : methodAnnotations) {
if (methodAnnotation instanceof POST){
this.httpMethod = "post";
this.relativeUrl = ((POST) methodAnnotation).value();
//是否有请求体, POST请求, 参数都是请求中
this.hashBody = true;
}else if (methodAnnotation instanceof GET){
this.httpMethod = "GET";
this.relativeUrl = ((GET) methodAnnotation).value();
this.hashBody = false;
}
}
/*
todo:2,解析方法参数上面的注解
*/
int length = parameterAnnotations.length;
parameterHandlers = new ParameterHandler[length];
for (int i = 0; i < length; i++) {
//一个参数上所有的注解
Annotation[] annotations = parameterAnnotations[i];
for (Annotation annotation : annotations) {
if (annotation instanceof Field) {
String value = ((Field) annotation).value();
parameterHandlers[i] = new ParameterHandler.FiledParameterHandler(value);
}else if (annotation instanceof Query){
String value = ((Query) annotation).value();
parameterHandlers[i] = new ParameterHandler.QueryParameterHandler(value);
}
}
}
return new ServiceMethod(this);
}
}
}
5,在ServiceMethod类里面还要需要对请求参数请求处理, 需要编写ParameterHandler类.
public abstract class ParameterHandler {
protected String key;
abstract void apply(ServiceMethod serviceMethod,String value);
static class QueryParameterHandler extends ParameterHandler{
public QueryParameterHandler(String key) {
this.key = key;
}
@Override
void apply(ServiceMethod serviceMethod, String value) {
serviceMethod.addQueryParameterHandler(key,value);
}
}
static class FiledParameterHandler extends ParameterHandler{
public FiledParameterHandler(String key) {
this.key = key;
}
@Override
void apply(ServiceMethod serviceMethod, String value) {
serviceMethod.addFiledParameter(key,value);
}
}
}
5,通过ZyangRetrofit类里面的调用 serviceMethod.invoke(args)的 方法,这个方法最终返回的是代理对象, 通过okhttp创建callFactory.newCall(request) 并返回
6,最后把ZyangRetrofit源码展示如下
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.Call;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
public class ZyangRetrofit {
// 因为在okhttp 需要一个 callFactory 例如 OkHttpClient();
final Call.Factory callFactory;
//这是okHttp url格式的baseUrl
final HttpUrl baseUrl;
final Map<Method,ServiceMethod> serviceMethodMap = new ConcurrentHashMap<>();
protected ZyangRetrofit(Call.Factory callFactory,HttpUrl baseUrl){
this.callFactory = callFactory;
this.baseUrl = baseUrl;
}
//通过动态代理构建service接口的代理对象.
public <T> T create(final 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 {
ServiceMethod serviceMethod = loadServiceMethod(method);
return serviceMethod.invoke(args);
}
});
}
/*
获取Method解析后的信息
*/
private ServiceMethod loadServiceMethod(Method method) {
ServiceMethod resultService = serviceMethodMap.get(method);
if (resultService != null){
return resultService;
}
synchronized (serviceMethodMap){
resultService = serviceMethodMap.get(method);
if (resultService == null){
resultService = new ServiceMethod.Builder(this,method).build();
serviceMethodMap.put(method,resultService);
}
}
return resultService;
}
/**
* 构建者模式, 将一个复杂对象的构建和本体进行分离, 可以使使用者不必知道内部组成的细节
*/
public static final class Builder{
private HttpUrl baseUrl;
//okhttp3.Call.Factory 有唯一一个实现类, 是OkhttpClient
private okhttp3.Call.Factory callFactory;
public Builder callFactory(okhttp3.Call.Factory factory){
this.callFactory = factory;
return this;
}
public Builder baseUrl(String baseUrl){
this.baseUrl = HttpUrl.get(baseUrl);
return this;
}
public ZyangRetrofit build(){
if (baseUrl == null){
throw new IllegalStateException("Base URL required");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null){
callFactory = new OkHttpClient();
}
return new ZyangRetrofit(callFactory,baseUrl);
}
}
}
总结, 上面的框架,大都是采用构建者模式,通过Builder去构建对象.
下面是框架的类图.
retrofit2.png
时序图
image.png
以上是模仿一个简单的Retrofit. 后面会有针对Retrofit源码详细讲解的文章,请大家关注.
网友评论