热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

反射+注解+retrofit+okhttp3总结

一键归纳okhttp3retrofit2架构,反射注解retrofit手写框架下面两篇文章是我觉得理解比较透彻和详细的文章一、首先你需要了解什么是动态代理Retr

一键归纳okhttp3+retrofit2架构,反射+注解+retrofit手写框架

下面两篇文章是我觉得理解比较透彻和详细的文章

一、首先你需要了解什么是动态代理

Retrofit源码学习之动态代理

二、其次你要了解一下retrofit2的基本使用以及源码解析

Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装。

从架构角度看Retrofit的作用、原理和启示

三、简单的利用注解反射实现retrofit网络请求,有助于理解其中的基本原理

此处仅为基本使用,适配器和转换器未使用。距离完整的框架还差一大截

下面开始看代码

元数据

public interface WeatherApi {@POST("/v3/weather/weatherInfo")@FormUrlEncodedCall postWeather(@Field("city") String city, @Field("key") String key);@GET("/v3/weather/weatherInfo")Call getWeather(@Query("city") String city, @Query("key") String key);
}

看一下自定义的注解,用于方法注解,适用于运行期

@Target(METHOD)
@Retention(RUNTIME)
public @interface GET {String value() default "";
}

@Target(METHOD)
@Retention(RUNTIME)
public @interface POST {String value() default "";
}

自定义的retrofit

public class MyRetrofit {final Map serviceMethodCache &#61; new ConcurrentHashMap<>();final Call.Factory callFactory;final HttpUrl baseUrl;MyRetrofit(Call.Factory callFactory, HttpUrl baseUrl) {this.callFactory &#61; callFactory;this.baseUrl &#61; baseUrl;}public T create(final Class service) {return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},new InvocationHandler() {&#64;Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//解析这个method 上所有的注解信息ServiceMethod serviceMethod &#61; loadServiceMethod(method);//args:return serviceMethod.invoke(args);}});}private ServiceMethod loadServiceMethod(Method method) {//先不上锁&#xff0c;避免synchronized的性能损失ServiceMethod result &#61; serviceMethodCache.get(method);if (result !&#61; null) return result;//多线程下&#xff0c;避免重复解析,synchronized (serviceMethodCache) {result &#61; serviceMethodCache.get(method);if (result &#61;&#61; null) {result &#61; new ServiceMethod.Builder(this, method).build();serviceMethodCache.put(method, result);}}return result;}/*** 构建者模式&#xff0c;将一个复杂对象的构建和它的表示分离&#xff0c;可以使使用者不必知道内部组成的细节。*/public static final class Builder {private HttpUrl baseUrl;//Okhttp->OkhttClientprivate okhttp3.Call.Factory callFactory; //nullpublic Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory &#61; factory;return this;}public Builder baseUrl(String baseUrl) {this.baseUrl &#61; HttpUrl.get(baseUrl);return this;}public MyRetrofit build() {if (baseUrl &#61;&#61; null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory &#61; this.callFactory;if (callFactory &#61;&#61; null) {callFactory &#61; new OkHttpClient();}return new MyRetrofit(callFactory, baseUrl);}}
}

接下来是ServiceMethod 记录请求类型 参数 完整地址

public class ServiceMethod {private final Call.Factory callFactory;private final String relativeUrl;private final boolean hasBody;private final ParameterHandler[] parameterHandler;private FormBody.Builder formBuild;HttpUrl baseUrl;String httpMethod;HttpUrl.Builder urlBuilder;public ServiceMethod(Builder builder) {//获取代理对象myretrofit的参数&#xff0c;以便封装请求参数baseUrl &#61; builder.enjoyRetrofit.baseUrl;callFactory &#61; builder.enjoyRetrofit.callFactory;httpMethod &#61; builder.httpMethod;relativeUrl &#61; builder.relativeUrl;hasBody &#61; builder.hasBody;parameterHandler &#61; builder.parameterHandler;//如果是有请求体,创建一个okhttp的请求体对象if (hasBody) {formBuild &#61; new FormBody.Builder();}}public Object invoke(Object[] args) {/*** 1 处理请求的地址与参数* 这里也是在invoke里要实现的网络请求*/for (int i &#61; 0; i }


public abstract class ParameterHandler {abstract void apply(ServiceMethod serviceMethod, String value);static class QueryParameterHandler extends ParameterHandler {String key;public QueryParameterHandler(String key) {this.key &#61; key;}//serviceMethod: 回调&#64;Overridevoid apply(ServiceMethod serviceMethod, String value) {serviceMethod.addQueryParameter(key,value);}}static class FiledParameterHandler extends ParameterHandler {String key;public FiledParameterHandler(String key) {this.key &#61; key;}&#64;Overridevoid apply(ServiceMethod serviceMethod, String value) {serviceMethod.addFiledParameter(key,value);}}
}

最后调用、点击事件卸在view里。不展示了

public class MainActivity extends AppCompatActivity {private static final String TAG &#61; "MainActivity";private EnjoyWeatherApi enjoyWeatherApi;&#64;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyRetrofit enjoyRetrofit &#61; new MyRetrofit.Builder().baseUrl("https://restapi.amap.com").build();enjoyWeatherApi &#61; enjoyRetrofit.create(EnjoyWeatherApi.class);}public void enjoyPost(View view) {okhttp3.Call call &#61; enjoyWeatherApi.postWeather("110101", "ae6c53e2186f33bbf240a12d80672d1b");call.enqueue(new okhttp3.Callback() {&#64;Overridepublic void onFailure(okhttp3.Call call, IOException e) {}&#64;Overridepublic void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {Log.i(TAG, "onResponse enjoy post: " &#43; response.body().string());response.close();}});}
}

 


推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
author-avatar
手机用户2602929277
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有