ImageVerifierCode 换一换
格式:DOCX , 页数:31 ,大小:32.36KB ,
资源ID:9532480      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/9532480.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(编译时注解Butterknife源码解析之深入篇刘永雷.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

编译时注解Butterknife源码解析之深入篇刘永雷.docx

1、编译时注解Butterknife源码解析之深入篇刘永雷编译时注解Butterknife源码解析之深入篇(雷惊风)1.概述。上篇文章我对Butterknife实现做了一些基础的说明,本篇文章我将向大家详细分析BindView、OnClick解析流程、生成BindingSet对应Java文件流程及我们调用ButterKnife.bind(this)后ButterKnife与生成Java文件的建立连接过程。2.BindView解析流程。这篇文章将接着上篇文章的findAndParseTargets(RoundEnvironment env)方法,如果你看了上篇文章,那么你就知道,所有Butterkn

2、ife中注解的解析都是在这个方法中的。好的那么我们开始吧。我们这个方法的流程上篇文章已经说过了,这里就不再浪费口水了,我们把解析BindView的代码拷出来再看一下:/ Process each BindView element./* * 处理BindView(R.id.btn)注解; * 1.做了一系列验证;如:private static修饰符判断、BindView必须作用在View上或者interface上等等; * 2.id的处理;生成QualifiedId、缓存等; * 3.builder创建;一个id是否注解了多次 * 4.Nullable处理,创建FieldViewBinding

3、存入builder,将enclosingElement存入erasedTargetNames; */for (Element element : env.getElementsAnnotatedWith(BindView.class) / we dont SuperficialValidation.validateElement(element) / so that an unresolved View type can be generated by later processing roundstry parseBindView(element, builderMap, erasedTar

4、getNames); catch (Exception e) logParsingError(element, BindView.class, e); 很简单,获取了项目中所有的被BindView注解了的Element,通过for()循环处理每一个,一个trycatch代码块,try中出问题,打印信息,关于在注解处理器中处理错误log信息,在这里就不讲了,可以在init()方法中获取Messager辅助类。看来重点在parseBindView(element, builderMap, erasedTargetNames);方法中了,跟进去:private void parseBindView(

5、Element element, Map builderMap, Set erasedTargetNames) /获取父级Element;TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();/ Start by verifying common generated code restrictions.boolean hasError = isInaccessibleViaGeneratedCode(BindView.class, fields, element) | isBindingInWron

6、gPackage(BindView.class, element);/ Verify that the target type extends from View.TypeMirror elementType = element.asType();if (elementType.getKind() = TypeKind.TYPEVAR) TypeVariable typeVariable = (TypeVariable) elementType; elementType = typeVariable.getUpperBound(); Name qualifiedName = enclosing

7、Element.getQualifiedName(); Name simpleName = element.getSimpleName();/BindView必须作用在View上或者interface上;if (!isSubtypeOfType(elementType, VIEW_TYPE) & !isInterface(elementType) if (elementType.getKind() = TypeKind.ERROR) note(element, %s field with unresolved type (%s) + must elsewhere be generated as

8、 a View or interface. (%s.%s),BindView.class.getSimpleName(), elementType, qualifiedName, simpleName); else error(element, %s fields must extend from View or be an interface. (%s.%s),BindView.class.getSimpleName(), qualifiedName, simpleName); hasError = true; if (hasError) return; / Assemble informa

9、tion on the field.int id = element.getAnnotation(BindView.class).value();/通过enclosingElement获取builder,每一个builder对应一个类,如activity;BindingSet.Builder builder = builderMap.get(enclosingElement);/将element所在包与id封装到QualifiedId中;QualifiedId qualifiedId = elementToQualifiedId(element, id);if (builder != null

10、) /判断当前BindView所修饰控件是否已经绑定过; /getId():将id存入Id对象,并存入symbols;String existingBindingName = builder.findExistingBindingName(getId(qualifiedId);if (existingBindingName != null) error(element, Attempt to use %s for an already bound ID %d on %s. (%s.%s),BindView.class.getSimpleName(), id, existingBindingNa

11、me, enclosingElement.getQualifiedName(), element.getSimpleName();return; else /新建一个builder;builder = getOrCreateBindingBuilder(builderMap, enclosingElement); String name = simpleName.toString(); TypeName type = TypeName.get(elementType);/判断是否添加了Nullableboolean required = isFieldRequired(element);/通过

12、Id创建ViewBinding.Builder并setFieldBinding(fieldViewBinding)builder.addField(getId(qualifiedId), new FieldViewBinding(name, type, required);/ Add the type-erased version to the valid binding targets set.erasedTargetNames.add(enclosingElement);方法也还好,不到100行,来看看在这个方法中做了一些什么操作吧。咱们先拿出一部分来看:/获取父级Element;Type

13、Element enclosingElement = (TypeElement) element.getEnclosingElement();/ Start by verifying common generated code restrictions.boolean hasError = isInaccessibleViaGeneratedCode(BindView.class, fields, element) | isBindingInWrongPackage(BindView.class, element);/ Verify that the target type extends f

14、rom View.TypeMirror elementType = element.asType();if (elementType.getKind() = TypeKind.TYPEVAR) TypeVariable typeVariable = (TypeVariable) elementType; elementType = typeVariable.getUpperBound();Name qualifiedName = enclosingElement.getQualifiedName();Name simpleName = element.getSimpleName();/Bind

15、View必须作用在View上或者interface上;if (!isSubtypeOfType(elementType, VIEW_TYPE) & !isInterface(elementType) if (elementType.getKind() = TypeKind.ERROR) note(element, %s field with unresolved type (%s) + must elsewhere be generated as a View or interface. (%s.%s),BindView.class.getSimpleName(), elementType,

16、qualifiedName, simpleName); else error(element, %s fields must extend from View or be an interface. (%s.%s),BindView.class.getSimpleName(), qualifiedName, simpleName); hasError = true; if (hasError) return;这部分是对我们BindView注解应用的一个正确性的一个检查,首先获取了我们的element对应的外部类的TypeElement,比如,activity中用BindView注解了一个But

17、ton btn;获取了activity对应的TypeElement,如果你看了上篇文章你就会明白。然后调用了一个isInaccessibleViaGeneratedCode(BindView.class, fields, element)方法与一个isBindingInWrongPackage(BindView.class, element)方法进行判断操作。一个一个来看一下,第一个:/* * 检查annotation作用域是否正确; * * param annotationClass* param targetThing* param element* return*/private boo

18、lean isInaccessibleViaGeneratedCode(Class annotationClass, String targetThing, Element element) boolean hasError = false;/获取当前element所在类的TypeElement;TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();/ Verify method modifiers.获取当前element的修饰符;Set modifiers = element.getModifie

19、rs();/修饰符不能是private或者static的,否则报告异常(error方法); / Messager提供给注解处理器一个报告错误、警告以及提示信息的途径。 / 它不是注解处理器开发者的日志工具,而是用来写一些信息给使用此注解器的第三方开发者的。if (modifiers.contains(PRIVATE) | modifiers.contains(STATIC) error(element, %s %s must not be private or static. (%s.%s), annotationClass.getSimpleName(), targetThing, encl

20、osingElement.getQualifiedName(), element.getSimpleName(); hasError = true; / Verify containing type.element只能直接从属于类(不能修饰局部变量);否则报错;if (enclosingElement.getKind() != CLASS) error(enclosingElement, %s %s may only be contained in classes. (%s.%s), annotationClass.getSimpleName(), targetThing, enclosing

21、Element.getQualifiedName(), element.getSimpleName(); hasError = true; / Verify containing class visibility is not private.element外层类不能是私有的,否则报错;if (enclosingElement.getModifiers().contains(PRIVATE) error(enclosingElement, %s %s may not be contained in private classes. (%s.%s), annotationClass.getSim

22、pleName(), targetThing, enclosingElement.getQualifiedName(), element.getSimpleName(); hasError = true; return hasError;在这个类中判断了三种非正常情况:1.BindView注解的Element为private或者static修饰报错,如下例子:BindView(R.id.btn) private Button btn; 这种情况下就会报错。2.当前Element不是直接在一个类里边,报错。如:在一个方法的局部变量上添加了注解。3.外部Element是private的报错。如:p

23、rivate class Activity extends . BindView(R.id.btn) private Button btn;再看一下isBindingInWrongPackage(BindView.class, element)方法:/* * 检查anitation注解是否作用在了系统类上; * * param annotationClass* param element* return*/private boolean isBindingInWrongPackage(Class annotationClass, Element element) TypeElement enc

24、losingElement = (TypeElement) element.getEnclosingElement(); String qualifiedName = enclosingElement.getQualifiedName().toString();/不能作用于Android系统类里;if (qualifiedName.startsWith(android.) error(element, %s-annotated class incorrectly in Android framework package. (%s), annotationClass.getSimpleName(

25、), qualifiedName);return true; /不能作用在java系统类中;if (qualifiedName.startsWith(java.) error(element, %s-annotated class incorrectly in Java framework package. (%s), annotationClass.getSimpleName(), qualifiedName);return true; return false;这个方法主要是检查我们是否用到了系统类上,这里注意我们自己定义的包名。接着回到上一个方法向下看,后续又检查了是否用在了View子类

26、上或者Interface上。我都加了注释,不在详细解释。如果上边检查有一步出问题,则return终止。到这里,检查我们应用BindView合法性就完了。再往下边走:/ Assemble information on the field.int id = element.getAnnotation(BindView.class).value();/通过enclosingElement获取builder,每一个builder对应一个类,如activity;BindingSet.Builder builder = builderMap.get(enclosingElement);/将element所

27、在包与id封装到QualifiedId中;QualifiedId qualifiedId = elementToQualifiedId(element, id);if (builder != null) /判断当前BindView所修饰控件是否已经绑定过; /getId():将id存入Id对象,并存入symbols;String existingBindingName = builder.findExistingBindingName(getId(qualifiedId);if (existingBindingName != null) error(element, Attempt to us

28、e %s for an already bound ID %d on %s. (%s.%s),BindView.class.getSimpleName(), id, existingBindingName, enclosingElement.getQualifiedName(), element.getSimpleName();return; else /新建一个builder;builder = getOrCreateBindingBuilder(builderMap, enclosingElement);首先获取到我们注解中指定的id,如下代码中的R.id.btn:BindView(R.i

29、d.btn)Button btn;查看builderMap中是否已经缓存了外部Element对应的BindingSet.Builder,通过id创建QualifiedId,看一下这个过程:private QualifiedId elementToQualifiedId(Element element, int id) return new QualifiedId(elementUtils.getPackageOf(element).getQualifiedName().toString(), id);这里用到了辅助类elementUtils获取element的包名,通过包名与id创建了Qual

30、ifiedId后边是builder判断,如果不为空,通过QualifiedId生成Id判断是否注解过相同id,注解过,则输出错误信息。Builder为空,调用getOrCreateBindingBuilder(builderMap, enclosingElement)创建或获取builder,看一下:private BindingSet.Builder getOrCreateBindingBuilder( Map builderMap, TypeElement enclosingElement) BindingSet.Builder builder = builderMap.get(enclosingElement);if (builder = null) /生成一个builder, / builder中保存了泛型信息、将要生成的类名称、是否Final修饰、是否View内部,是否Activity内部、是否Dialog内部;builder = BindingSet.newB

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1