手动实现ioc框架

上传人:小** 文档编号:88105924 上传时间:2019-04-19 格式:DOC 页数:10 大小:66.50KB
返回 下载 相关 举报
手动实现ioc框架_第1页
第1页 / 共10页
手动实现ioc框架_第2页
第2页 / 共10页
手动实现ioc框架_第3页
第3页 / 共10页
手动实现ioc框架_第4页
第4页 / 共10页
手动实现ioc框架_第5页
第5页 / 共10页
点击查看更多>>
资源描述

《手动实现ioc框架》由会员分享,可在线阅读,更多相关《手动实现ioc框架(10页珍藏版)》请在金锄头文库上搜索。

1、手动实现IOC框架自序在开发Android中,总要写许多的findViewById方法,这无疑是一件非常痛苦的事情。直到接触了Xutils框架,发现竟然可以使用注解的方式,优雅的干掉了findViewById方法,当时真是惊为天人。后来遇到了Butterknife之后,发现不仅能够通过实现findViewById方法,甚至连setOnClickListener,getString(),getResource()方法,都能通过一行注解的方式快速的实现。当时在使用过程中,感觉这种方式大大的提高了开发的效率,以及编码的舒畅度,自己很有必要实现以下。于是便有了这篇博客,该篇博客主要实现了findVie

2、wById方法,虽然广度不是很大,但他们的原理都是相同的。如何使用使用方式和Butterknife相似,通过注解BindView标识控件,通过ViewFinder.inject(this)实现代码的注入。public class MainActivity extends AppCompatActivity / 通过注解绑定控件 BindView(R.id.text) TextView textView; Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);

3、setContentView(R.layout.activity_main); /代码注入 ViewFinder.inject(this); textView.setText(123); 实现原理实现方式有两种通过反射实现:如果对于反射有深入了解,则应该清楚,我们可以通过反射获取到该注解,并且获取到该注解的值等等一系列的必须量,通过反射我们实现对控件的注入。该方法虽然可以实现,但对效率有着一定的影响。毕竟反射很影响效率。通过编译器生成代码实现:在我们运行Java代码的时候,通常先通过javac将java文件编译成.class文件,然后运行class文件,那么我们能不能够在编译时期,根据我们的注

4、解生成findViewById等方法,这样我们就能够在运行期查找控件。结果当然是可以的,本例就是使用这种方式。因为虽然其使用的是注解,但在运行期其实质仍是通过findViewById方法查找控件,相比于反射来说,大大的提高了性能。通过编译器生成代码的大致流程如下:编写Modul:ioc-annotation,该工程主要定义注解BindView用以修饰变量。编写Modul:ioc-compiler,该工程为最终会打成jar包,主要是在javac编译时期根据注解生成注入代码的相关类编写Modul:ioc-api,该工程主要提供注入的调用方法ViewFidder.inject(),调用代码注入的方法

5、。编写Modul:app,测试工程。代码实现根据上面的流程,开始实现框架编写ioc-annotation模块该模块比较简单,就是定义一个注解。如下:Retention(RetentionPolicy.CLASS)Target(ElementType.FIELD)public interface BindView int value();该注解主要有两个功能:在Activity中修饰变量,用以标识需要findViewById的相关控件。在ioc-compiler模块中,用以检索和获取需要findViewById的控件。编写ioc-compiler模块在之前我们提到过,该框架的原理是在编译时期根据

6、我们的要求生成注入的辅助代码,那么如何生成,以何种规则生成,肯定是由我们来定义的。javac命令中,可以在其编译的指定目录放入一个.jar文件,当然这个.jar文件有特殊的要求(后面再说),这样运行javac命令之前,javac会调用jar,通过这种特性订制一些我们想实现的功能。那么看一下该模块的关键类IocProcessorAutoService(Processor.class)public class IocProcessor extends AbstractProcessor / 文件相关的辅助类,生成JavaSouceCode private Filer mFileUtils; pri

7、vate Elements mElementUtils; / 日志相关 private Messager mMessager; private Types mTypeUtils; Override public synchronized void init(ProcessingEnvironment processingEnvironment) super.init(processingEnvironment); mTypeUtils = processingEnvironment.getTypeUtils(); mFileUtils = processingEnvironment.getFi

8、ler(); mElementUtils = processingEnvironment.getElementUtils(); mMessager = processingEnv.getMessager(); /* * 标示该处理器捕获处理的注解类型 */ Override public Set getSupportedAnnotationTypes() Set annotationTypes = new LinkedHashSet(); / getCanonicalName 获取规范的名字 annotationTypes.add(BindView.class.getCanonicalName

9、(); return annotationTypes; /* * 指定使用的java版本,一般默认支持返回最新 * return */ Override public SourceVersion getSupportedSourceVersion() return SourceVersion.latestSupported(); private Map mProxyMap = new HashMap(); /* * 相当于main 函数,处理扫描,评估和处理注解的代码以及生成java文件 * param set * param roundEnvironment 用于查询包含特定注解的注解元素

10、* return */ Override public boolean process(Set set, RoundEnvironment roundEnvironment) /.关键处理代码 return true; 为了方便浏览,暂时删去了一些代码。首先在类的声明上,我们添加了一个注解AutoService,该注解是由Google提供的用于生成.jar包的相关注解。使用该注解需要添加依赖com.google.auto.service:auto-service:1.0-rc3,在这里有一个疑问,为什么要使用该注解呢,生成的jar包邮什么特殊的地方吗?因为该jar包是提供于注解时期的,所以其有

11、特殊的目录形式:除了有最基本的类以外,多了META-INF的service目录,该目录中的文件命名是固定的,其内容很简单com.example.IocProcessor就一行内容,标明主要的处理类。而如果我们手动编写jar的目录很麻烦,所以Google提供了一个AutoService,用以直接实现这种目录形式的jar包。看完注解之后,看类声明,继承AbstractProcessor,实现三个方法:getSupportedAnnotationTypes:获取注解支持的类型,在此,我们支持BindView,没有什么疑问getSupportedSourceVersion:指定使用的java版本,一般

12、默认支持返回最新,默认此写法,没什么问题。process:处理注解的主要方法,主要在此方法中实现对相关类的处理。那么看一下process的实现: private Map mProxyMap = new HashMap(); /* * 相当于main 函数,处理扫描,评估和处理注解的代码以及生成java文件 * param set * param roundEnvironment 用于查询包含特定注解的注解元素 * return */ Override public boolean process(Set set, RoundEnvironment roundEnvironment) mProx

13、yMap.clear(); / -检索注解,保存包含注解的类以及需要注入的成员变量- / 该方法获取的element是被注解标注的所有元素,所以需要检查 Set elements = roundEnvironment.getElementsAnnotatedWith(BindView.class); for (Element element : elements) / 检查element的类型 if (!checkAnnotationValid(element, BindView.class) return false; VariableElement variableElement = (VariableElement) element); TypeElement typeElement = (TypeElement) variableElement.getEnclosingElement(); / 全路径名 String qual

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 商业/管理/HR > 管理学资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号