公司项目里用的是版本7.0.1。以下就以7.0.1为例
以ButterKnife在activity中绑定为例;
ButterKnife.bind(this)
bind(target, target, Finder.ACTIVITY);
Finder枚举
static void bind(Object target, Object source, Finder finder) {
Class<?> targetClass = target.getClass();
try {
if (debug) Log.d(TAG, "Looking up view binder for " + targetClass.getName());
ViewBinder<Object> viewBinder = findViewBinderForClass(targetClass);
if (viewBinder != null) {
viewBinder.bind(finder, target, source);
}
} catch (Exception e) {
throw new RuntimeException("Unable to bind views for " + targetClass.getName(), e);
}
}
private static ViewBinder<Object> findViewBinderForClass(Class<?> cls)
throws IllegalAccessException, InstantiationException {
ViewBinder<Object> viewBinder = BINDERS.get(cls);//根据Class查找viewBinder
if (viewBinder != null) {
if (debug) Log.d(TAG, "HIT: Cached in view binder map.");
return viewBinder;
}
String clsName = cls.getName();
if (clsName.startsWith(ANDROID_PREFIX) || clsName.startsWith(JAVA_PREFIX)) {//android.或者java.为开头包名的
if (debug) Log.d(TAG, "MISS: Reached framework class. Abandoning search.");
return NOP_VIEW_BINDER;
}
try {
Class<?> viewBindingClass = Class.forName(clsName + ButterKnifeProcessor.SUFFIX);//如xxx.MainActivity$$ViewBinder
//noinspection unchecked
viewBinder = (ViewBinder<Object>) viewBindingClass.newInstance();
if (debug) Log.d(TAG, "HIT: Loaded view binder class.");
} catch (ClassNotFoundException e) {
if (debug) Log.d(TAG, "Not found. Trying superclass " + cls.getSuperclass().getName());
viewBinder = findViewBinderForClass(cls.getSuperclass());
}
BINDERS.put(cls, viewBinder);//保存这个viewBinder到LinkedHashMap.
return viewBinder;
}
public <T> T findRequiredView(Object source, int id, String who) {
T view = findOptionalView(source, id, who);
if (view == null) {
String name = getContext(source).getResources().getResourceEntryName(id);
throw new IllegalStateException("Required view '"
+ name
+ "' with ID "
+ id
+ " for "
+ who
+ " was not found. If this view is optional add '@Nullable' annotation.");
}
return view;
}
public <T> T findOptionalView(Object source, int id, String who) {
View view = findView(source, id);
return castView(view, id, who);
}
通过枚举类中的方法获取view:
public enum Finder {
.....
ACTIVITY {
@Override protected View findView(Object source, int id) {
return ((Activity) source).findViewById(id);
}
}
通过泛型转化得到真正的view:
public <T> T castView(View view, int id, String who) {
try {
return (T) view;
} catch (ClassCastException e) {
if (who == null) {
throw new AssertionError();
}
String name = view.getResources().getResourceEntryName(id);
throw new IllegalStateException("View '"
+ name
+ "' with ID "
+ id
+ " for "
+ who
+ " was of the wrong type. See cause for more info.", e);
}
}
public <T> T findRequiredView(Object source, int id, String who) {
T view = findOptionalView(source, id, who);
if (view == null) {
String name = getContext(source).getResources().getResourceEntryName(id);
throw new IllegalStateException("Required view '"
+ name
+ "' with ID "
+ id
+ " for "
+ who
+ " was not found. If this view is optional add '@Nullable' annotation.");
}
return view;
}
解析注解生成的MainActivity$$ViewBinder.class内容:
public class MainActivity$$ViewBinder<T extends MainActivity>implements ButterKnife.ViewBinder<T> {
public void bind(ButterKnife.Finder finder, T target, Object source) {
View view = (View) finder.findRequiredView(source, 2131624181, "field 'llAlert' and method 'onClick'");
target.llAlert = ((LinearLayout) finder.castView(view, 2131624181, "field 'llAlert'"));
view.setOnClickListener(new MainActivity..ViewBinder .1 (this, target));
.....
}
public void unbind(T target) {
target.llAlert = null;
.....
}
}
编译时注解处理基于annotation processing tool:
1、自定义类继承自 javax.annotation.processing.AbstractProcessor
2、重写其中的 process 函数
在编译时自动查找所有继承自 AbstractProcessor 的类,然后调用他们的 process 方法去处理。
ButterKnife中继承AbstractProcessor的是ButterKnifeProcessor类.