This is the fifth day of my participation in Gwen Challenge
ButterKnife is a tool that automates page findViewById from the famed JakeWharton. Of course, it has stopped updating for now. Please post a note on Github:
Attention: This tool is now deprecated. Please switch to view binding. Existing versions will continue to work, obviously, but only critical bug fixes for integration with AGP will be considered. Feature development and general bug fixes have stopped.
So how does such a useful tool work? To predict details, let’s look at the source code.
The first is easy to use. After introducing dependencies, add methods to the Activity onCreate method by adding @bindView annotations to the view you want to process
ButterKnife.bind(this);
Copy the code
Run.
So what does this bind method do first?
@NonNull @UiThread
public static Unbinder bind(@NonNull Activity target) {
// 1. First get the decorView
View sourceView = target.getWindow().getDecorView();
return bind(target, sourceView);
}
@NonNull @UiThread
public static Unbinder bind(@NonNull Object target, @NonNull View source) {
// 2. Obtain class, find the correspondingClass<? > targetClass = target.getClass(); Constructor<? extends Unbinder> constructor = findBindingConstructorForClass(targetClass);if (constructor == null) {
return Unbinder.EMPTY;
}
// 6. Create an object by reflection
try {
return constructor.newInstance(target, source);
} catch (IllegalAccessException e) {
// Delete the catch statement}}Copy the code
@VisibleForTesting
static finalMap<Class<? >, Constructor<? extends Unbinder>> BINDINGS =new LinkedHashMap<>();
@Nullable @CheckResult @UiThread
private staticConstructor<? extends Unbinder> findBindingConstructorForClass(Class<? > cls) {// 3. Look in the constructor cache and return if found
Constructor<? extends Unbinder> bindingCtor = BINDINGS.get(cls);
if(bindingCtor ! =null || BINDINGS.containsKey(cls)) {
return bindingCtor;
}
// 4. Filter system classes by class prefix
String clsName = cls.getName();
if (clsName.startsWith("android.") || clsName.startsWith("java.")
|| clsName.startsWith("androidx.")) {
if (debug) Log.d(TAG, "MISS: Reached framework class. Abandoning search.");
return null;
}
// 5. Load the classes automatically generated by the ButterKnife help through reflection and get the constructor
try{ Class<? > bindingClass = cls.getClassLoader().loadClass(clsName +"_ViewBinding");
//noinspection unchecked
bindingCtor = (Constructor<? extends Unbinder>) bindingClass.getConstructor(cls, View.class);
} // omit the catch statement
BINDINGS.put(cls, bindingCtor);
return bindingCtor;
}
Copy the code
See what ButterKnife’s auto-generated classes look like
public class ButterKnifeTestActivity_ViewBinding implements Unbinder {
private ButterKnifeTestActivity target;
@UiThread
public ButterKnifeTestActivity_ViewBinding(ButterKnifeTestActivity target) {
this(target, target.getWindow().getDecorView());
}
// 7. When we get to here, we can see that our view is bound
// target.btnFirst: the view attribute defined in the page cannot be private
@UiThread
public ButterKnifeTestActivity_ViewBinding(ButterKnifeTestActivity target, View source) {
this.target = target;
target.btnFirst = Utils.findRequiredViewAsType(source, R.id.btnFirst, "field 'btnFirst'", Button.class);
}
@Override
@CallSuper
public void unbind(a) {
ButterKnifeTestActivity target = this.target;
if (target == null) throw new IllegalStateException("Bindings already cleared.");
this.target = null;
target.btnFirst = null; }}Copy the code
That’s the basic process, but the whole thing is that when we compile, we generate the relevant class file based on our annotations, and then we use reflection to call findViewById. A set of operations flowing smoothly, really have to admire the wisdom of god ah.
We can pay attention to the BINDINGS Map, through the Map to cache data, avoid multiple times through reflection to obtain, improve efficiency. This idea is often used when writing code. Yes, did you?
This article is a personal learning record, can not avoid mistakes or not enough in-depth understanding of technical points, but also hope for criticism and advice.