ButterKnife實現原理

代碼自動生成

  • 使用代碼自動生成,一是爲了提升編碼的效率,二十避免在運行期大量使用反射,經過在編譯期利用反射生成輔助類和方法以供運行時使用

註解處理器步驟

  • 在java編譯器中構建java

  • 編譯器開始執行未執行過的註解處理器markdown

  • 玄幻處理註解元素,找到被該住解所修飾的類,方法或者屬性this

  • 生成對應的類,並寫入文件編碼

  • 判斷是否全部的註解處理器都已執行完畢,若是沒有,繼續下一個註解處理器的執行(回到步驟1)spa

圖一

註解處理器的實現

  • 主要須要兩個庫的AutoServiceJavapoet,對全部的註解進行處理並生成以_BindView結尾的輔助類輔助類中是註解的實現(findViewByid,onCclick等)code

  • 註解處理器須要實現AbstractProcessor接口,並實現對應的方法:init(),getSupportedSourceVersion(),getSupportedAnnotationTypes(),(返回所須要的處理的註解被process()方法接收), process() 方法必須實現,掃描全部備註接的元素並作處理,在這裏完成了目標類信息的收集並生成對應 java 類,返回值類型是boolean,true表示該註解已被處理,不但願下一個註解處理器繼續處理,false表示未被處理,下一個註解處理器繼續處理orm

可用註解和反射實現

  • 拿BindView爲例:首先建立BindView註解,參數爲默認 int value()
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface BindView {
    int value();
}
複製代碼
  • 在相應的類中進行引用:
@BindView(R.id.text1)
TextView textView1;

@BindView(R.id.text2)
TextView textView2;
複製代碼
  • 經過反射進行綁定 ButterKnife.bind(this);
public static void bind(Activity activity) {
    bindView(activity);
}

//經過反射實現註解的綁定
public static void bindView(Activity activity) {
    try {
        // 獲取字節碼對象
        Class<? extends Activity> aClass = activity.getClass();

        // 獲取所有變量
        Field[] fields = aClass.getDeclaredFields();

        // 遍歷所有變量
        for (Field field : fields) {
            // 容許暴力反射
            field.setAccessible(true);

            // 獲取帶有註解BindView的變量
            BindView annotation = field.getAnnotation(BindView.class);

            if (annotation != null) {
                // 獲取註解的值
                int value = annotation.value();
                View view = activity.findViewById(value);
                field.set(activity, view);
            }
        }
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
複製代碼
相關文章
相關標籤/搜索