深入理解ButterKnife源码并掌握原理(四)
2016-09-10 22:33
676 查看
到此我们整个的流程算分析完了。
最后我们看下对外提供的API
ButterKnife.bind(this);方法。
我们看一下ButterKnife对外提供的API
我们看到bind的一系列方法都会调用createBinding方法
Class<\?> (?是转义字符csdn要不支持)targetClass = target.getClass();获取类的实例,最后获取构造函数,最后constructor.newInstance方法来调用该类的构造函数。
而该类的构造函数是通过findBindingConstructorForClass方法,我可没来看下此方法:
可以看到用到了简单的缓存。
采用了接口的形式。让生成的类来实现,比如:
那如何unbind呢??
ButterKnife.bind(this)返回值是一个我们生成的java文件类的实例对象。返回的是一个Unbinder 正和此意。
so,你可以这么用:
到此我们就算完了。
下一篇我们讲自己来实现类似butterknife的demo,这样我们才能正在的会学,会用。
下一篇
深入理解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 @UiThread public 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 @UiThread public 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 @UiThread public 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 @UiThread public 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 @UiThread public 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 @UiThread public 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 @UiThread private 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 { @UiThread public SimpleAdapter$ViewHolder_ViewBinding(SimpleAdapter.ViewHolder target, View source) { //... } //... @Override public 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); } @Override protected void onDestroy() { super.onDestroy(); unbinder.unbind(); }
到此我们就算完了。
下一篇我们讲自己来实现类似butterknife的demo,这样我们才能正在的会学,会用。
下一篇
深入理解ButterKnife源码并掌握原理(五)
相关文章推荐
- 深入理解ButterKnife源码并掌握原理(二)
- 深入理解ButterKnife源码并掌握原理(五)
- 深入理解ButterKnife源码并掌握原理(一)
- 深入理解ButterKnife源码并掌握原理(三)
- 深入理解编译注解(六)Butterknife的实现原理
- 深入理解Spark 2.1 Core (五):Standalone模式运行的原理与源码分析
- 深入理解Spark 2.1 Core (六):资源调度的原理与源码分析
- 深入理解Spark 2.1 Core (十):Shuffle Map 端的原理与源码分析
- 深入理解Spark 2.1 Core (二):DAG调度器的原理与源码分析
- 深入理解Spark 2.1 Core (十一):Shuffle Reduce 端的原理与源码分析
- 深入理解Spark 2.1 Core (一):RDD的原理与源码分析
- 深入理解Spark 2.1 Core (四):运算结果处理和容错的原理与源码分析
- 深入理解Spark 2.1 Core (十二):TimSort 的原理与源码分析
- 深入理解PHP原理之源码目录结构
- 深入理解Spark 2.1 Core (八):Standalone模式容错及HA的原理与源码分析
- 深入理解Spark 2.1 Core (十二):TimSort 的原理与源码分析
- 深入理解Spark 2.1 Core (四):运算结果处理和容错的原理与源码分析
- 深入理解Spark 2.1 Core (八):Standalone模式容错及HA的原理与源码分析
- 深入理解Spark 2.1 Core (六):Standalone模式运行的原理与源码分析
- 深入理解Spark 2.1 Core (三):任务调度器的原理与源码分析