您的位置:首页
xUtils3源码分析(一):view的绑定
2016-07-14 11:21
302 查看
概述
xUtils3是国人开发的一款功能丰富的Android快速开发框架,值得研究下。zip包下载:[ZIP]
xutils主要分以下几个模块
视图绑定模块
网络请求模块
数据库模块
图片加载模块
我们将逐一透过源码分析,本文分析视图绑定模块,包含
View的注入和
View事件的注入。
我们将项目导入AndroidStudio,项目结构:
项目结构
xutils为项目源码,sample为使用方法举例。
我们通过分析sample这个示例项目来分析xutils的内部细节。
首先我们看看
MyApplication这个类:
MyApplication
xUtils3在初始化的时候必须在自定义的
Application中来完成初始化,代码为
x.Ext.init(this);,首先就涉及到了这个
x类,我们打开看看:
/** * Created by wyouflf on 15/6/10. * 任务控制中心, http, image, db, view注入等接口的入口. * 需要在在application的onCreate中初始化: x.Ext.init(this); */ public final class x { ...省略代码 }
通过类注释我们可以看到
x类是所有模块的入口。
那我们看看
x.Ext这个内部类:
x.Ext
该类提供了一系列的静态成员变量,和对应的
set方法,对应了
xutils提供的几个功能模块。
看看
init方法:
x.Ext.init(Application app)方法
很明显将
Application绑定到
app上,方便全局调用。
接下来我们分模块说明:
View注入
我们找到一个BaseActivity:
BaseActivity
在
Activity的
onCreate方法中,调用:
x.view().inject(this)来完成视图注解框架的初始化。
看看
view()方法做了什么:
x.view()
该方法是用来进行
Ext.viewInjector的初始化的,那么我们到
ViewInjectorImpl看看
ViewInjectorImpl.registerInstance();是如何初始化的:
ViewInjectorImpl.registerInstance()
非常清楚,一个单例模式,而
ViewInjectorImpl其实实现了
ViewInjector接口:
ViewInjectorImpl实现了ViewInjector接口
看看
ViewInjector接口:
ViewInjector
该接口的说明很明了,就是可以不同对象类型进行视图注入,如
View,
Avtivity,以及
ViewHolder,
fragment,以满足各个场景的使用。
那我们进入到具体的
Activity进行分析吧:
MainActivity
可以看到
MainActivity继承了
BaseActivity,另外我们可以很明显的看到两种注解:
@ContentView(id)和
@ViewInject(id),我们先看看
ContentView注解的源码:
ContentView
@Target(ElementType.TYPE)说明了该注解作用于类,接口或者枚举类型上。
@Retention(RetentionPolicy.RUNTIME)说明该注解会一直保留到JVM运行时。
int Value()说明可以注解参数的类型为
int类型;
那么
@ContentView(R.layout.activity_main)放入的就是布局
activity_main的
id值。
再来看看
ViewInject注解:
ViewInject
@Target(ElementType.FIELD)说明该组件作用在成员变量上。
@Retention(RetentionPolicy.RUNTIME)说明该注解会保留到JVM运行时。
int value();说明注解参数类型为
int,而
int parentId() default 0说明可以填写一个父View的id,默认为0。
关于
java注解的基本使用,大家可以自行搜索。
现在我们知道了两个注解的作用:
ContentView注解是用来注入主布局界面的,而
ViewInject注解是用来注入具体控件的。
那么当
MainActivity回调
onCreate方法时,因为继承了
BaseActivity,所以自然就走到
BaseActivity的
onCreate方法:
BaseActivity
那么接下来我们看看这个
x.view().inject(this);中的
inject(this)实现方法吧:
x.view().inject(this)
先获取了传入
Activity的
Class对象,然后将这个
Class作为参数传入
findContentView(handlerType)方法,从名字就可以看出该方法肯定是获取
ContentView的注解对象的:
findContentView(handlerType)
该方法也是比较简单的,首先判断了
thisCls是不是
null,或者是不是非法的
Class,看下
IGNORED:
IGNORED
这里看到
IGNORED是一个
HashSet保存了一些需要忽略的
Class对象。
通过检测后
ContentView contentView = thisCls.getAnnotation(ContentView.class);这句代码其实就是获取
thisCls上的注解
ContentView类,这里就是
MainActivity上的
ContentView注解。
如果获取的
ContentView为
null就继续在
thisCls的父类中获取。
这样我们分析完了
findContentView(handlerType)方法,作用就是获取传入类或父类上的注解
ContentView类。
我们继续回到
inject()方法,获取到
ContentView注解后,如果不为
null那么就通过
int viewId = contentView.value();获取注解中填写的
id值,也就是
R.layout.activity_main的值,然后
获取注解中填写的 id 值
之后就是通过反射获取
MainActivity上的
setContentView方法,然后再反射调用该方法,将布局id值
R.layout.activity_main设置上去,这样就完成了
MainActivity布局的设置,基本原理就是通过注解+反射,还是比较简单的。
最后一句代码:
injectObject()
首先我们看看方法中的第三个参数是个
ViewFinder对象,将
MainActivity通过构造传递进去了。
先看看这个
ViewFinder类的内容:
ViewFinder
该类的主要作用就是用于获取绑定的
View对象,就是将
View和
Activity的
findViewById方法进行封装,先大致了解下。
然后再返回
injectObject()方法,该方法较长,一部分一部分的贴出:
检测参数是否合法
首先还是检测是否是合法的类,然后:
递归调用
这里进行递归调用,然后是重点:
核心代码
146行是获取所有声明的字段,这里我们就是
MainActivity中的字段了,然后开始循环。
150-157行是检测字段是不是合法的类型,如果合法才能继续。
159行就是获取字段上的
ViewInject注解类。
162行就是如果获取到的
ViewInject类不为
null,就将
ViewInject注解中填写的
viewid和父
viewid作为参数传递给
finder类来获取绑定的
View对象,回顾下
MainActivity中的字段:
被注解的字段
可以看到只写了
view的id,并没有写父
view的id,那么父
view的id就是默认值
0了。
明白了再看看
ViewFinder类中:
findViewById方法
36-38行就是说如果
pid大于
0,那么就获取父
view对象,看看
findViewById()方法:
重载的 findViewById方法
这里就是封装了
findViewById方法,适用于
View对象或者
Activity,这里我们是
Activity。
继续看40-45行,因为我们没有写
pid所以代码执行44行,这样我们就获取到了绑定的
View对象了。
这样我们再回到
ViewInjectorImpl类的
injectObject(...)方法:
反射设置 view 对象
这里就很清楚了,如果获取的
View对象不为
null,那么通过反射调用,将
View对象设置到
field上,这样就完成了一个视图控件的绑定,过程并不是很复杂。
文/悠嘻侠(简书作者)
原文链接:http://www.jianshu.com/p/7791f3b8c234
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
相关文章推荐
- OSSEC 安装执行./install.sh详细信息
- 二叉搜索树的总结
- Android 开发系统自带语音模块应用
- 说说实际开发中的那些冲突
- 汉字截取
- lazy(懒加载)模式和异步加载模式详解
- 机器学习训练集之traing 、validation、test data set
- Android提高第七篇之XML解析与生成
- 【Android实测】调起系统浏览器打开指定页面代码
- 掌握新变革,解密新趋势|msup第29届MPD软件管理工作坊成功召开
- 【OpenCV】根据点集(轮廓)拟合圆
- 深圳国税代开发票流程
- Gadgets-生成随即字符串(JS-JAVA)
- Android中Acitvity跳转动画效果实现
- mysql主从同步报错
- android基础
- css3
- Codeforces 687A NP-Hard Problem
- 解析java中main函数为什么是这样写
- 【刷题之路】调整数组顺序使奇数位于偶数前面