(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~
注解反射动态代理实现简版Retrofit
文章目录
1.Retrofit简介
Retrofit是一个RESTful的HTTP网络请求框架的封装,网络请求的工作本质上是OkHttp完成,而Retrofit仅负责网络请求接口的封装。
2.Retrofit基本使用
(1)url由baseUrl与path拼接而成组成完整的地址。
(2)参数在get与post两个方法当中进行传递
(3)通过Retrofit的create方法,将接口对象传递进去,就可以使用接口对象调用接口里面的方法,即可得到一个Call<ResponseBody>.
(4)这个call对象有一个enqueue方法来进行异步请求
2.1构建者设计模式
2.1.1有什么好处?
(1)可以将一个复杂对象的构建和它的表示分离,可以使使用者不必知道内部组成的细节。
(2)构建者类会有很多成员变量或方法,表现层不需要关心其实现的细节,如变量的初值检查与设置等。
3.简易版retrofit实现
3.1实现时序图与逻辑
(1)执行代理方法
(2)反射获取方法上的注解
(3)反射获取方法参数上的注解
(4)记录请求参数中的参数名称
3.2构建自定义的Retrofit
3.2.1构建
/**
* 构建者模式,将一个复杂对象的构建和它的表现层分离,可以使使用者不用关心细节的实现
* 这个类会有很多成员变量或方法,不需要关心其实现的细节
*/
public static final class Builder{
private HttpUrl baseUrl;
private Call.Factory callFactory;
public Builder callFactory(Call.Factory factory){
this.callFactory = callFactory;
return this;
}
public Builder baseUrl(String baseUrl){
this.baseUrl = HttpUrl.get(baseUrl);
return this;
}
/**
* 1.build()方法用于对属性做检查
* 1.1只需要关心哪些成员是想要去设置的
* @return
*/
public CustomRetrofit build(){
if(null == baseUrl){
throw new IllegalStateException("Base URL required.");
}
Call.Factory callFactory = this.callFactory;
if(null == callFactory){
callFactory = new OkHttpClient();
}
return new CustomRetrofit(callFactory,baseUrl);
}
}
3.2.2创建请求代理类
3.2.2.1定义请求注解
@Target({ElementType.METHOD})//指定注解作用于类的哪些元素上面
@Retention(RetentionPolicy.RUNTIME)//注解由JVM保留,在运行时可以使用它
public @interface POST {
String value() default "";
}
@Target({ElementType.METHOD})//指定此注解可作用于类的哪些元素上
@Retention(RetentionPolicy.RUNTIME)//设置注解保留级别为RUNTIME,即可由JVM保留,在运行时还可以使用它
public @interface GET {
String value() default "";
}
3.2.2.2定义请求接口
public interface CustomWeatherApi {
@POST("/v3/weather/weatherInfo")
Call postWeather(@Field("city") String city,@Field("key")String key);
@GET("/v3/weather/weatherInfo")
Call getWeather(@Query("city") String city,@Query("key")String key);
}
3.2.2.3创建接口实现类
/**
* 1.目的
* 1.1返回一个接口的对象给外部
* 1.2通过动态代理的方式去创建该接口的具体实现类对象
*
* 2.定义泛型方法
* 2.1在访问修饰符与返回类型之间加个<T>,表示该方法为泛型方法
* 2.2T:表示泛型方法的返回值也是一个泛型
* 2.3.Class<T> service:是使用泛型作为泛型方法的参数
*
* 3.解析方法上的所有注解信息
* 3.1完成url的拼接
* 3.2完成方法的调用
*
* @param service:指的是CustomWeatherApi接口的class对象,此处用泛型参数去接收
* @param <T>
* @return
*/
public <T> T create(final Class<T> service){
InvocationHandler ih = new InvocationHandler() {
/**
* 执行代理对象的任意一个方法,都会使得invoke()方法获得执行。
* @param o
* @param method
* @param objects
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//1.解析这个方法上所有的注解信息
//1.1就能够知道需要通过哪种请求方式(get与post)请求
//1.2通知知道请求哪一个方法
ServiceMethod serviceMethod = loadServiceMethod(method);
//1.3执行方法
return serviceMethod.invoke(objects);
}
};
//使用动态代理创建CustomWeatherApi接口的实现类对象
return (T) Proxy.newProxyInstance(service.getClassLoader(),
new Class[]{service},ih);
}
/**
* 解析方法上的所有注解信息
* @param method
* @return
*/
private ServiceMethod loadServiceMethod(Method method) {
//1.从缓存中取出方法相关的信息
ServiceMethod result = serviceMethodCache.get(method);
if(null != result){
return result;
}
//2.利用同步代码块细粒度的上锁
synchronized (serviceMethodCache){
//2.1先从缓存中取方法信息
result = serviceMethodCache.get(method);
//2.2判断是否有方法信息,没有则新建后放入缓存
if(null == result){
result = new ServiceMethod.Builder(this,method).build();
serviceMethodCache.put(method,result);
}
}
return result;
}
3.3构建方法解析器
3.3.1GET请求参数注解
@Target({ ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Query {
String value() default "";
}
3.3.2POST请求参数注解
@Target({ ElementType.PARAMETER})//指定该注解可以运用于标记类的哪些元素上面,此处为方法参数
@Retention(RetentionPolicy.RUNTIME)//指定注解保留级别为RUNTIME级别,可由JVM保留,即在JVM运行的时候还可以使用它
public @interface Field {
String value() default "";
}
3.3.3构建方法解析器对象
public static class Builder{
private final CustomRetrofit retrofit;
//存放方法上的所有注解
private final Annotation[] methodAnnotations;
//存放方法参数里面的所有注解信息
private final Annotation[][] parameterAnnotations;
//存放方法参数请求的key
private ParameterHandler[] parameterHandlerArr;
//记录当前的请求方式
private String httpMethod;
//记录请求url的path
private String relativeUrl;
//判断是否有请求体
private boolean hasBody;
/**
* 1.外部传递需要
* 2.Method method
*/
public Builder(CustomRetrofit retrofit, Method method){
this.retrofit = retrofit;
this.methodAnnotations = method.getAnnotations();
this.parameterAnnotations = method.getParameterAnnotations();
}
/**
* 1.在build方法中对成员变量做相应的设置
* @return
*/
public ServiceMethod build(){
for(Annotation methodAnnotation : methodAnnotations){
if(methodAnnotation instanceof POST){
this.httpMethod = "POST";
this.relativeUrl = ((POST) methodAnnotation).value();
this.hasBody = true;
}else if(methodAnnotation instanceof GET){
this.httpMethod = "GET";
this.relativeUrl = ((GET) methodAnnotation).value();
this.hasBody = false;
}
}
//2.解析方法参数的注解
int length = parameterAnnotations.length;
parameterHandlerArr = new ParameterHandler[length];
for(int i =0; i < length; i++){
//2.1取得一个参数上的所有注解
Annotation[] annotations = parameterAnnotations[i];
for(Annotation annotation : annotations){
//方法参数被Field注解修饰的为post请求,被Query注解修饰的为get请求
if(annotation instanceof Field){
//得到注解上的value,即获取请求参数的中的key
String value = ((Field)annotation).value();
parameterHandlerArr[i] =
new ParameterHandler.FieldParameterHandler(value);
}else if(annotation instanceof Query){
String value = ((Query)annotation).value();
parameterHandlerArr[i] =
new ParameterHandler.QueryParameterHandler(value);
}
}
}
return new ServiceMethod(this);
}
}
3.3.4构建参数处理器
public abstract class ParameterHandler {
abstract void apply(ServiceMethod serviceMethod,String value);
/**
* get请求的参数拼接
*/
static class QueryParameterHandler extends ParameterHandler{
String key;
public QueryParameterHandler(String key) {
this.key = key;
}
@Override
void apply(ServiceMethod serviceMethod, String value) {
//拼接方法参数到url中
serviceMethod.addQueryParameter(key,value);
}
}
/**
* post请求的参数拼接
*/
static class FieldParameterHandler extends ParameterHandler{
String key;
public FieldParameterHandler(String key) {
this.key = key;
}
@Override
void apply(ServiceMethod serviceMethod, String value) {
serviceMethod.addFieldParameter(key,value);
}
}
}
3.3.5参数拼接
//get请求,把参数key与value拼接到请求url中
public void addQueryParameter(String key, String value) {
if(null == urlBuilder){
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
urlBuilder.addQueryParameter(key,value);
}
//post请求,将参数key与value直接添加到表单请求体中。
public void addFieldParameter(String key, String value) {
formBuild.add(key,value);
}
3.4请求方法调用执行
//执行方法
public Object invoke(Object[] args){
/**
* 1.处理请求的地址与参数
*/
for(int i = 0; i < parameterHandlerArr.length; i++){
ParameterHandler handler = parameterHandlerArr[i];
//为参数中的key设置对应的值
handler.apply(this,args[i].toString());
}
//获取最终请求地址
HttpUrl url;
if(null == urlBuilder){
urlBuilder = baseUrl.newBuilder(relativeUrl);
}
url = urlBuilder.build();
//post请求时的表单请求体
FormBody formBody = null;
if(null != formBuild){
formBody = formBuild.build();
}
Request request =
new Request.Builder().url(url).method(httpMethod,formBody).build();
return callFactory.newCall(request);
}
3.5.客户端调用
//通过注解、反射、动态代理自定义retrofit,实现post请求与get请求
CustomRetrofit customRetrofit = new CustomRetrofit.Builder().baseUrl(baseUrl).build();
//customWeatherApi对象其实是一个代理对象,然后通过这个代理对象去执行get方法和post方法。
customWeatherApi = customRetrofit.create(CustomWeatherApi.class);
btn_myretrofit_post.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
okhttp3.Call call = customWeatherApi.postWeather("110101", "ae6c53e2186f33bbf240a12d80672d1b");
call.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
if(response.isSuccessful()){
Log.i(CUSTOM_TAG,
"onResponse enjoy post: " + response.body().string());
response.close();
}
}
});
}
});
4.打赏鼓励
感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!