Android 玩转IOC,Retfotit源码解析,教你徒手实现自定义的Retrofit框架
CSDN:码小白
原文地址:
http://blog.csdn.net/sk719887916/article/details/51957819
前言
Retrofit用法和介绍的文章实在是多的数不清,也有很多介绍其内部原理的,但是看过之后,还是让很多人云里雾里, 本篇文章旨在通过自我实现一个自定义的Retrofit,来熟悉了解其Retrofit的内部原理。也帮助针对那些项目很稳定,解决迁移API接口带来的难度问题。
如果对Retrofit不熟悉的请先阅读Retrofit全介绍:
Retrofit :https://futurestud.io/blog
回顾Retrofit
Retrofit2.0是SQUARE美国一家移动支付公司最新发布的在Android平台上http访问客户端,具体简单用法列举
简单列子
// 创建ApiService
public interface ApiService {
@GET("service/getIpInfo.php") Call<IpResult> getData(@Query("ip") String ip);
}
// 实例化Retrofit
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(url)
.build();
// 构架ApiServiceImpl
ApiService apiService = retrofit.create(ApiService.class);
// 执行异步请求
Call<IpResult> call = apiService.getData("21.22.11.33");
call.enqueue(new Callback<IpResult>() {
@Override
public void onResponse(Call<IpResult> call, Response<IpResult> response) {
}
@Override
public void onFailure(Call<IpResult> call, Throwable t) {
}
});
代码很简洁,很多人甚是羡慕,想想自己何时才能写出如此优雅的代码,也想弄明白其内部怎么实现的,今天就给大家带来一款Tamic框架,来模仿下Retrofit的实现原理。
下文开始之前,不会对Retrofit的原理进行理论分析,其实也没这个必要,推荐一篇其他人写的文章:
接着本次实现方式不会沿用Retrofit基于的okhttp, 因为okHttp本身实现了已进行了线程管理和回调,会给本次demo实现带来一定弊端,所以我选择用了SynchttpClient来做基础请求端,这样才能显得用零基础实现Retrofit, 本次实现需要涉猎到Java反射,依赖注入,控制反转,代理模式,建造者模式,面向接口编程等,这些技术这里不再重复介绍,下面接着看重点。
准备注解类
retrofit采用注解实现API,因此也模仿了准备多个注解接口,比如请求类型(GET),参数(Part),头部(header)等,
为了区分我用Tamic的开头用来做前缀先创建一个注解类TGet
// 请求方式
@Target(ElementType.METHOD)
public @interface TGet {
String value();
}
Body 类似于Part
// 参数
@Retention(RetentionPolicy.RUNTIME)
public @interface TBody {
String value();
}
其他注解类没多大技术点,就不在列举
准备CallBack
此接口类用来回调http请求结果,采用泛型,方便上层注入数据model,动态解析返回实体
public interface ICallback<T> {
void success(T t);
void failed(Throwable e);
}
Platform
Platform用来调度多个请求线程,
public class Platform {
private static final Platform PLATFORM = findPlatform();
public static Platform get() {
Log.v(TamicHttpClient.TAG, PLATFORM.getClass().toString());
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
public Executor defaultCallbackExecutor() {
return new HandleThreadPool().getExecutor();
}
public Object execute(Runnable runnable) {
defaultCallbackExecutor().execute(runnable);
return null;
}
static class Android extends Platform {
@Override
public Executor defaultCallbackExecutor() {
return new HandleThreadPool().getExecutor();
}
}
Tamic
构建类似Retrofit一样的bulid模式的API工厂,此类主要用反射解析和代理ApiService,用来执行具体网络访问请求,动态解析泛型数据模型,回调服务端返回的请求结果,返回上层便于UI更新。
Tamic(Context context, String baseUrl, AsyncHttpClient client) {
this.context = context;
this.baseUrl = baseUrl;
this.client = client;
}
/**
* public interface CategoryService {
* @POST("category/{cat}/")
* Call<List<Item>> categoryList(@Path("cat") String a, @Query("page") int b);
* }
*/
public <T> T create(final Class<T> clazz) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(),
new Class[]{clazz},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
performeParser(proxy, method, args);
return execute();
}
});
}
此是Tamic内部类builder大致图,具体代码可以去文章结尾所示的github地址上去阅读,主要用来构建上层添加baseUrl,超时等接口,实例化AsyncHttpClient等
线程池工厂
用来管理和复用线程,避免线程溢出造成内存泄露,不是本次关注的点,略去
实现好了自己的Retrofit,接下来我们看看怎样使用,观察下和Retrofit用法有什么区别?
Tamic用法
实例化Tamic (Retrofit)
Tamic tamic = new Tamic.Builder(MainActivity.this)
.baseUrl("http://ip.taobao.com/")
.connectTimeout(5)
.addLog(true)
.build();
APIService
public interface ApiService {
@TGet("service/getIpInfo.php")
Call<IpResult> getData(@TBody("ip") String ip,ICallback<IpResult> callBack);
}
Create Service
ApiService service = tamic.create(ApiService.class);
Execute
service.getData("21.22.11.33", new ICallback<IpResult>() {
@Override
public void success(IpResult ipResult) {
// todo
}
@Override
public void failed(Throwable e) {
// todo
}
});
华丽结束
给下面按钮给个点击事件,用来执行请求,在回调中显示一条Toast, 看看测试结果:
数据成功请求到,并且被框架自动解析返回JavaBean
既然功能和Retrofit很相似,和我们的Retrofit几乎一摸一样,我们再看看的工程配置
compile ‘com.loopj.android:android-async-http:1.4.9’
compile ‘com.alibaba:fastjson:1.2.12’
果不其然,并没有关于Retrofit的任何依赖,说明我们的Tamic并无投机取巧。
本次实现只关注Retrofit整体了一个流程思想,其他Retrofit的功能其实就通过以上思想来扩展的,设置解析工厂,返回内容格式,文件上传,下载等,本次实现并没有深入模仿,因为Retrofit整个流程思想比较系统,其他Api和普通Get请求一样,稍微改造一下就可以了。
与其说是对Retrofit的借鉴,还不如是对Ioc和Aop思想的综合运用。大家也发现本次主要学习依赖注入,和控反转的AOP思想,以及加入代理和接口编程,旨在以后的开发道路上能自我实现一种开发框架,如果感兴趣的同学可以去自我模仿一个RxJava.
如果你目前项目非常大,网络接口一直以前的httpclient的朋友,可以大但的迁移到Retrofit,只要你稍微做下接口适配,就能很好的让老旧Api接通Retrofit,或者也可以将老Api改造成属于你的Retrofit请求端!领导都无法阻止你用Retrofit的步伐…
最后感谢淘宝的测试地址:
URL:”http://ip.taobao.com/service/getIpInfo.php?ip=21.22.11.33“;
源码下载:
https://github.com/NeglectedByBoss/Tamic_Retrofit
导读:
- Retrofit 2.0
超能实践,完美支持Https传输
- Retrofit2.0
完美同步Cookie实现免登录
Android 玩转IOC,Retfotit源码解析,教你徒手实现自定义的Retrofit框架的更多相关文章
- Android IntentService使用介绍以及源码解析
版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...
- Android Handler机制(四)---Handler源码解析
Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, l ...
- 【Android应用开发】EasyDialog 源码解析
示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...
- Android Handler机制(三)----Looper源码解析
一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...
- Android Handler机制(二)---MessageQueue源码解析
MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...
- Android View 事件分发机制 源码解析 (上)
一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...
- Android FM 模块学习之四 源码解析(1)
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 前一章我们了解了FM手动调频,接下 ...
- Android HandlerThread使用介绍以及源码解析
摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.HandlerThread的介绍及使用举例 HandlerThread是什么鬼?其本质就是一个线程,但是Han ...
- Android FM模块学习之四源码解析(一)
转自:http://blog.csdn.net/tfslovexizi/article/details/41516149?utm_source=tuicool&utm_medium=refer ...
随机推荐
- Centos常用命令之:VI
在Linux中,对文件内容的编辑莫过去vi命令了,它是每个发布版本中的标配.并且功能强大. 在vi中一共有三种模式,一般模式(命令参照),编辑模式(命令参照)与命令模式(命令参照). ◇一般模式:当我 ...
- [HNOI2009]有趣的数列
题目描述 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足a1<a3<...<a2n ...
- 【BZOJ3506】【Cqoi2014】排序机械臂
传送门(因为BZOJ上没有题面...所以放的是luogu的) 题意:你需要维护一个序列,支持区间翻转与查询区间最小. 解题思路:由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解 ...
- hdu 5667 BestCoder Round #80 矩阵快速幂
Sequence Accepts: 59 Submissions: 650 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536 ...
- 习题9-3 UVA1629(dp)
Cake Slicing 题意:有一个n行m列的网格上有一些黑点,要求进行切割,使最后每块上只有一个黑点,求最少的刀数 思路:记忆化搜索,枚举每一条边来切,每一次搜索自己所能切割的所有情况取最小值 但 ...
- K-means聚类 的 Python 实现
K-means聚类 的 Python 实现 K-means聚类是一个聚类算法用来将 n 个点分成 k 个集群. 算法有3步: 1.初始化– K 个初始质心会被随机生成 2.分配 – K 集群通过关联到 ...
- Java 反射 Method threw 'java.lang.InstantiationException' exception.
查看这个InstantiationException:异常的api所说的是: 当应用程序试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该 ...
- IOS UITextView支持输入、复制、粘贴、剪切自定义表情
UITextView是ios的富文本编辑控件,除了文字还可以插入图片等.今天主要介绍一下UITextView对自定义表情的处理. 1.首先识别出文本中的表情文本,然后在对应的位置插入NSTextAtt ...
- Linux 在线模拟器
最近在学习Linux的一些命令的使用,但是很久之前装的Linux虚拟机被删掉了,又不想为了练习几个命令折腾一遍虚拟机.所以,就尝试地搜了一下,看看有没有在线的Linux模拟器可以使用,只要可以练习一下 ...
- 16. 3Sum Closest(中等)
Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...