概述

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
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

xUtils3源码分析(一):view的绑定的更多相关文章

  1. Android事件分发机制浅谈(三)--源码分析(View篇)

    写事件分发源码分析的时候很纠结,网上的许多博文都是先分析的View,后分析ViewGroup.因为我一开始理解的时候是按我的流程图往下走的,感觉方向很对,单是具体分析的时候总是磕磕绊绊的,老要跳到Vi ...

  2. springMVC源码分析--视图View(一)

    之前的博客springMVC源码分析--HttpMessageConverter数据转化(一)中我们已经介绍了数据返回值的处理,在博客springMVC源码分析--ViewResolver视图解析器( ...

  3. Android应用层View绘制流程与源码分析

    1  背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...

  4. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  5. jquery2源码分析系列

    学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...

  6. [转]jQuery源码分析系列

    文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...

  7. Android源码分析—深入认识AsyncTask内部机制

    本文转载http://blog.csdn.net/singwhatiwanna/article/details/17596225该博主博文,谢谢该博主提供的好文章! 前言 什么是AsyncTask,相 ...

  8. springMVC源码分析--页面跳转RedirectView(三)

    之前两篇博客springMVC源码分析--视图View(一)和springMVC源码分析--视图AbstractView和InternalResourceView(二)中我们已经简单的介绍了View相 ...

  9. springMVC源码分析--视图AbstractView和InternalResourceView(二)

    上一篇博客springMVC源码分析--视图View(一)中我们介绍了简单介绍了View的结构实现及运行流程,接下来我们介绍一下View的实现类做的处理操作. AbstractView实现了rende ...

随机推荐

  1. 由Python的super()函数想到的

    python-super *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !im ...

  2. 项目知识点.Part3

    内存管理: 基本数据类型或者Core Foundation对象都没有引用计数 主线程会自动创建释放池,子线程需要手动创建释放池. 具体的区别:http://www.cnblogs.com/langti ...

  3. 项目知识点.Part2

    1. 取消collectionView头视图重叠情况:以下两种情况效果一样 但是有一点点bug 每次remove之后 需要把视图刷到上面才会显示(后续会改进方法) for (UIView *view ...

  4. 转:《IIC时序》

    I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备.I2C总线产生于在80年代,最初为音频和视频设备开发,如今主 ...

  5. Network Saboteur

    poj2531:http://poj.org/problem?id=2531 题意:给你一个图,图中点之间会有边权,现在问题是把图分成两部分,使得两部分之间边权之和最大.题解:一开始比知道怎么办,想用 ...

  6. Keil MDK入门---从新建一个工程开始

    熟悉Keil C51的朋友对于Keil MDK上手应该比较容易,毕竟界面是很像的.但ARM内核毕竟不同于51内核,因此无论在设置上还是在编程思想上,都需要下番功夫研究的.本文以MDK V4.03为例, ...

  7. VS在Release模式下,难道还可以Debug?

    就是这段代码: int main(int argc, char *argv[]) { QApplication a(argc, argv); cxcxsdee w; w.show(); QString ...

  8. 【Linux】鸟哥的Linux私房菜基础学习篇整理(十一)

    1. 直接将命令丢到后台中执行“&”,在命令最后加“&”.    将目前的工作丢到后台中暂停:[Ctrl]+z 2. jobs [-lrs]:查看目前的后台工作状态.参数:-l:除了列 ...

  9. LA 4726 再看斜率优化

    感觉最近一批解题报告没写,现在慢慢补吧,算是noip前攒攒rp了 首先感到深深的自责,因为之前对斜率优化没有深入的理解,只是记住了一般步骤,并没有完全了解为什么这样做 先就这道题目而言 首先这种序列题 ...

  10. 【动态规划】Vijos P1218 数字游戏(NOIP2003普及组)

    题目链接: https://vijos.org/p/1218 题目大意: 一个N个数的环,分成M块,块内的数求和%10,最后每块地值累乘,求最大和最小. n(1≤n≤50)和m(1≤m≤9)太小了可以 ...