最后
如果觉得本文对你有帮助的话,不妨给我点个赞,关注一下吧!
https://www.wanandroid.com/article/query?k=butterknife
Android主流三方库源码分析(七、深入理解ButterKnife源码)
1、Butterknife原理
===================
讲到butterknife的原理。这里不得不提一下一般这种注入框架都是运行时注解,即声明注解的生命周期为RUNTIME,然后在运行的时候通过反射完成注入,这种方式虽然简单,但是这种方式多多少少会有性能的损耗。那么有没有一种方法能解决这种性能的损耗呢? 没错,答案肯定是有的,那就是Butterknife用的APT(Annotation Processing Tool)编译时解析技术。
注意:Butterknife是不使用反射的。
APT大概就是你声明的注解的生命周期为CLASS,然后继承AbstractProcessor类。继承这个类后,在编译的时候,编译器会扫描所有带有你要处理的注解的类,然后再调用AbstractProcessor的process方法,对注解进行处理,那么我们就可以在处理的时候,动态生成绑定事件或者控件的java代码,然后在运行的时候,直接调用bind方法完成绑定。
其实这种方式的好处是我们不用再一遍一遍地写findViewById和onClick了,这个框架在编译的时候帮我们自动生成了这些代码,然后在运行的时候调用就行了。
2、源码解析
======
版本:
//butterknife
implementation ‘com.jakewharton:butterknife:10.2.1’
annotationProcessor ‘com.jakewharton:butterknife-compiler:10.2.1’
拿到源码的第一步是从我们调用的地方来突破,那我们就来看看程序里面是怎样调用它的呢?
@BindView(R.id.btn100)
Button btn100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
@OnClick(R.id.btn100)
public void onViewClicked() {
}
我们直接就从 **ButterKnife.bind(this)**入手吧,点进来看看:
@NonNull @UiThread
public static Unbinder bind(@NonNull Activity target) {
View sourceView = target.getWindow().getDecorView();
return bind(target, sourceView);
}
根据activity得到DecorView,再传递到bind。
@NonNull @UiThread
public static Unbinder bind(@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);
}
}
言尽于此,完结
无论是一个初级的 coder,高级的程序员,还是顶级的系统架构师,应该都有深刻的领会到设计模式的重要性。
- 第一,设计模式能让专业人之间交流方便,如下:
程序员A:这里我用了XXX设计模式
程序员B:那我大致了解你程序的设计思路了
- 第二,易维护
项目经理:今天客户有这样一个需求…
程序员:明白了,这里我使用了XXX设计模式,所以改起来很快
- 第三,设计模式是编程经验的总结
程序员A:B,你怎么想到要这样去构建你的代码
程序员B:在我学习了XXX设计模式之后,好像自然而然就感觉这样写能避免一些问题
- 第四,学习设计模式并不是必须的
程序员A:B,你这段代码使用的是XXX设计模式对吗?
程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的
从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!
搜集费时费力,能看到此处的都是真爱!
片转存中…(img-hT3xhugR-1715815502167)]
搜集费时费力,能看到此处的都是真爱!