深入理解ButterKnife源码并掌握原理(四)
到此我们整个的流程算分析完了。
最后我们看下对外提供的API
bind 方法
那么还差一步,什么时候都要我们生成的java文件呢?答案是:
ButterKnife.bind(this);方法。
我们看一下ButterKnife对外提供的API
/*** BindView annotated fields and methods in the specified {@link Activity}. The current content* view is used as the view root.** @param target Target activity for view binding.*/@NonNull @UiThreadpublic static Unbinder bind(@NonNull Activity target) {View sourceView = target.getWindow().getDecorView();return createBinding(target, sourceView);}/*** BindView annotated fields and methods in the specified {@link View}. The view and its children* are used as the view root.** @param target Target view for view binding.*/@NonNull @UiThreadpublic static Unbinder bind(@NonNull View target) {return createBinding(target, target);}/*** BindView annotated fields and methods in the specified {@link Dialog}. The current content* view is used as the view root.** @param target Target dialog for view binding.*/@NonNull @UiThreadpublic static Unbinder bind(@NonNull Dialog target) {View sourceView = target.getWindow().getDecorView();return createBinding(target, sourceView);}/*** BindView annotated fields and methods in the specified {@code target} using the {@code source}* {@link Activity} as the view root.** @param target Target class for view binding.* @param source Activity on which IDs will be looked up.*/@NonNull @UiThreadpublic static Unbinder bind(@NonNull Object target, @NonNull Activity source) {View sourceView = source.getWindow().getDecorView();return createBinding(target, sourceView);}/*** BindView annotated fields and methods in the specified {@code target} using the {@code source}* {@link View} as the view root.** @param target Target class for view binding.* @param source View root on which IDs will be looked up.*/@NonNull @UiThreadpublic static Unbinder bind(@NonNull Object target, @NonNull View source) {return createBinding(target, source);}/*** BindView annotated fields and methods in the specified {@code target} using the {@code source}* {@link Dialog} as the view root.** @param target Target class for view binding.* @param source Dialog on which IDs will be looked up.*/@NonNull @UiThreadpublic static Unbinder bind(@NonNull Object target, @NonNull Dialog source) {View sourceView = source.getWindow().getDecorView();return createBinding(target, sourceView);}private static Unbinder createBinding(@NonNull Object target, @NonNull View source) {Class<?> targetClass = target.getClass();if (debug) Log.d(TAG, "Looking up binding for " + targetClass.getName());Constructor<? extends Unbinder> constructor = findBindingConstructorForClass(targetClass);if (constructor == null) {return Unbinder.EMPTY;}//noinspection TryWithIdenticalCatches Resolves to API 19+ only type.try {return constructor.newInstance(target, source);} catch (IllegalAccessException e) {throw new RuntimeException("Unable to invoke " + constructor, e);} catch (InstantiationException e) {throw new RuntimeException("Unable to invoke " + constructor, e);} catch (InvocationTargetException e) {Throwable cause = e.getCause();if (cause instanceof RuntimeException) {throw (RuntimeException) cause;}if (cause instanceof Error) {throw (Error) cause;}throw new RuntimeException("Unable to create binding instance.", cause);}}
我们看到bind的一系列方法都会调用createBinding方法
private static Unbinder createBinding(@NonNull Object target, @NonNull View source) {Class<?> targetClass = target.getClass();if (debug) Log.d(TAG, "Looking up binding for " + targetClass.getName());Constructor<? extends Unbinder> constructor = findBindingConstructorForClass(targetClass);if (constructor == null) {return Unbinder.EMPTY;}//noinspection TryWithIdenticalCatches Resolves to API 19+ only type.try {return constructor.newInstance(target, source);} catch (IllegalAccessException e) {throw new RuntimeException("Unable to invoke " + constructor, e);} catch (InstantiationException e) {throw new RuntimeException("Unable to invoke " + constructor, e);} catch (InvocationTargetException e) {Throwable cause = e.getCause();if (cause instanceof RuntimeException) {throw (RuntimeException) cause;}if (cause instanceof Error) {throw (Error) cause;}throw new RuntimeException("Unable to create binding instance.", cause);}}
Class<\?> (?是转义字符csdn要不支持)targetClass = target.getClass();获取类的实例,最后获取构造函数,最后constructor.newInstance方法来调用该类的构造函数。
而该类的构造函数是通过findBindingConstructorForClass方法,我可没来看下此方法:
@Nullable @CheckResult @UiThreadprivate static Constructor<? extends Unbinder> findBindingConstructorForClass(Class<?> cls) {//缓存中查找,找到直接返回Constructor<? extends Unbinder> bindingCtor = BINDINGS.get(cls);if (bindingCtor != null) {if (debug) Log.d(TAG, "HIT: Cached in binding map.");return bindingCtor;}//检查合法性String clsName = cls.getName();if (clsName.startsWith("android.") || clsName.startsWith("java.")) {if (debug) Log.d(TAG, "MISS: Reached framework class. Abandoning search.");return null;}try {//构造一个class,可以看类名就是我们生成的。Class<?> bindingClass = Class.forName(clsName + "_ViewBinding");//noinspection unchecked// 获取我们的构造函数bindingCtor = (Constructor<? extends Unbinder>) bindingClass.getConstructor(cls, View.class);if (debug) Log.d(TAG, "HIT: Loaded binding class and constructor.");} catch (ClassNotFoundException e) {if (debug) Log.d(TAG, "Not found. Trying superclass " + cls.getSuperclass().getName());bindingCtor = findBindingConstructorForClass(cls.getSuperclass());} catch (NoSuchMethodException e) {throw new RuntimeException("Unable to find binding constructor for " + clsName, e);}//加入到缓存中BINDINGS.put(cls, bindingCtor);return bindingCtor;}
可以看到用到了简单的缓存。
unbind 方法
在新版的8.4.0中去除了 unbind方法。
ButterKnife.unbind(this);
采用了接口的形式。让生成的类来实现,比如:
public final class SimpleAdapter$ViewHolder_ViewBinding implements Unbinder {@UiThreadpublic SimpleAdapter$ViewHolder_ViewBinding(SimpleAdapter.ViewHolder target, View source) {//...}//...@Overridepublic void unbind() {/...}}
那如何unbind呢??
ButterKnife.bind(this)返回值是一个我们生成的java文件类的实例对象。返回的是一个Unbinder 正和此意。
so,你可以这么用:
private Unbinder unbinder; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.simple_activity);unbinder=ButterKnife.bind(this);}@Overrideprotected void onDestroy() {super.onDestroy();unbinder.unbind();}
到此我们就算完了。
下一篇我们讲自己来实现类似butterknife的demo,这样我们才能正在的会学,会用。
下一篇
深入理解ButterKnife源码并掌握原理(五)
深入理解ButterKnife源码并掌握原理(四)相关推荐
- 深入理解ButterKnife源码并掌握原理(三)
上两篇我们分析完了处理器的process方法的findAndParseTargets方法来获取了一个集合,该集合包含了你使用注解的类的TypeElement和这个类中的注解的实例BindingClas ...
- 深入理解ButterKnife源码并掌握原理(二)
好,我们接着parseBindView的步骤3 ,忘记了在哪里了,咦. 可以看下上一篇,哈哈. 步骤3 BindingClass bindingClass = targetClassMap.get(e ...
- 深入理解ButterKnife源码并掌握原理(一)
前言 话说在android这座大山里,有一座庙(方块公司-square),庙里住着一个神-jake(我是这么叫的嘻嘻). 不要小看这个小jake,这个神可是为android应用开发们提供了强有力的帮助 ...
- 深入理解ButterKnife源码并掌握原理(五)
前面四篇是自己参考有关知识和分析ButterKnife源码后写的,如果有不对的地方,还望指导下. 这一篇是实践篇.我们的目的是学会原理来变为自己的知识. 这个demo所使用的原理就是ButterKni ...
- MyBatis 源码分析 - 缓存原理
1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...
- Tomcat7.0源码分析——请求原理分析(上)
前言 谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多早期的J2EE项目,由程序 ...
- 【赠书福利】掘金爆火小册同名《Spring Boot源码解读与原理剖析》正式出书了!...
关注我们丨文末赠书 承载着作者的厚望,掘金爆火小册同名读物<Spring Boot源码解读与原理剖析>正式出书! 本书前身是掘金社区销量TOP的小册--<Spring Boot源码解 ...
- 遍历HashMap源码——红黑树原理、HashMap红黑树实现与反树型化(三)
本章将是HashMap源码的最后一章,将介绍红黑树及其实现,HashMap的remove方法与反树型化.长文预警~~ 遍历HashMap源码--红黑树原理.HashMap红黑树实现与反树型化 什么是红 ...
- Java基础笔记(2)——HashMap的源码,实现原理,底层结构是怎么样的
Java基础笔记(2)--HashMap的源码,实现原理,底层结构是怎么样的 HashMap的源码,实现原理,底层结构 1.HashMap: HashMap是基于哈希表的 Map 接口的实现.此实现提 ...
最新文章
- 关于python赋值语句下列选项中描述正确的是_关于Python的分支结构,以下选项中描述正确的是()。...
- 基于nginx实现反向代理
- HTML5实现屏幕手势解锁(转载)
- c语言字符串数组的合并,C语言实现合并字符串
- xml文件 卷积神经网络_理解卷积神经网络中的输入与输出形状(Keras实现)
- 在centos上搭建redis集群并附测试(真集群非伪集群)
- 力扣- - 最短回文串(KMP算法)
- oraoledb.oracle 12c,关于OraOLEDB.Oracle找不到驱动问题的一种可能解决方案
- 百度AI智能小程序正式开放申请
- 罗永浩回应被列入老赖名单:就算“卖艺”也会把债务还完
- android 10 apk 存储适配,AndroidQ(10) 分区存储适配方法
- Spring mvc 参数类型转换
- 实验一 框架的选择及其原因
- 使用memcachedclientXmemcached与Spring整合
- Filecoin网络目前总质押量约为4110万枚FIL
- 二分法实战教学快速入门(折半查找法)
- Android Vendor Test Suite (VTS) 作用及测试方法
- 系统架构师必须掌握的英语单词
- JAVA POI EXCEL导出工具方法 支持冻结列行和设置不可编辑整行整列
- 计算机如何理解图像?
热门文章
- (转)SQL Server数据库状态监控 - 作业状态
- B-TrunC标准加入ITU集群国际标准
- SQL Server中CTE的另一种递归方式-从底层向上递归
- 开源 免费 java CMS - FreeCMS1.3-信息管理
- 【转载】用备份进行Active Directory的灾难重建:Active Directory系列之三
- 在django中实现表单
- MySQL更新行和插入列的语句
- oracle改表结构非空字段类型,oracle 表结构的非完全复制
- java判断integer是否为空_java安全编码指南之:表达式规则
- 学土木结构考计算机等级考试,请教各位,我是学土木的,考计算机二级的哪个比较好?...