安卓to鴻蒙系列:ButterKnife(一)

目錄:html

一、基礎知識java

二、寫一個乞丐版的ButterKnifegit

三、總結github

 

本文是關於ButterKnife的移植的第一篇:api

先介紹基礎知識,理解apt是什麼,最終輸出一個乞丐版BufferKnife注入工具。數組

這是讀懂BufferKnife源碼的基礎。app

第二篇佔坑:具體講解BufferKnife的移植。框架


基礎知識

apt技術的實際應用:

  • Android Databinding綁定viewide

  • ButterKnife綁定view工具

  • Dagger2注入變量

  • ARouter生成路由表

真的好多,很重要。apt就是生產力工具!

什麼是apt?

通俗講:apt就是javac對外開放的一個插件,使javac在編譯期間獲取註解(Annotation),並作出相應的處理(多數都是生成一些java代碼)。

從上圖能夠看出apt處理的是 java源文件 ,在編譯期介入。

與之對比的是asm之類的工具,處理的是字節碼文件,在編譯後期介入。

apt與javac的約定

apt與javac約定在META-INF/services/javax.annotation.processing.Processor文件中註冊apt插件。這樣apt就參與到javac的編譯過程當中了。

寫一個乞丐版BufferKnife

不想看文字,直接看源碼,點擊 https://gitee.com/andych008/aptDemo

初始代碼fork自 https://github.com/LiMubai2017/aptDemo ,先對做者表示感謝。


乞丐版BufferKnife做爲一款view注入工具,主要乾了3件事,

  1. 解析註解
  2. 處理註解(生成模板類文件)
  3. 經過模板類注入view對象

第0步:準備工做

先定義註解BindView,被@BindView標記的變量會被注入。

通常註解都定義在一個單獨的module(如取名apt-annotation),由於它會被apt-compiler和apt-api都依賴,屬於公共代碼。

apt-compiler是apt的主要代碼所在,完成註解的解析、模板文件的生成。

apt-api則是對外的工具類,供用戶使用,完成注入操做。

app是demo,其中定義了

@BindView(value = ResourceTable.Id_text_helloworld)
public Text testTextView;

第一步:解析註解

在apt-compiler中定義類BindViewProcessor繼承javax.annotation.processing.AbstractProcessor,實現其中的getSupportedAnnotationTypes()該方法註冊要解析的註解。

第二步:處理註解(生成模板文件)

BindViewProcessor中實現process()方法,處理註解。

先理解javax.lang.model.element.Elementjavax.lang.model.type.TypeMirror,參考這裏 有詳細的解釋。

簡單講:

Element是描述java語言元素的類,好比包、類、變量、參數等。

TypeMirror是描述Element類型的類,好比各類基本類型、數組、類等。

很繞,只有多用才能真正理解。好比:demo中testTextView就是VariableElement元素類型

TypeElement enclosingElement = (TypeElement) variableElement.getEnclosingElement();//獲取表明MainAbility的TypeElement

String field = variableElement.getSimpleName().toString();//testTextView
TypeMirror typeMirror = variableElement.asType();//ohos.agp.components.Text

經過log()方法,可使用Messager打日誌,驗證咱們的理解。

log(String.format("element : (%s) %s ", element.getKind(), element));
log(String.format("bind : (%s) %s <--> id = %d", typeMirror, field, id));
輸出日誌:
注: element : (FIELD) testTextView 
注: bind : (ohos.agp.components.Text) testTextView <--> id = 16777222

generateCodeByPoet()方法中,使用javapoet生成模板代碼MainAbility$$Autobind.java(文件路徑app/build/generated/source/annotation/debug/com/example/apt_demo/MainAbility$$Autobind.java

關於javapoet的使用,直接看官方文檔吧:https://github.com/square/javapoet

解釋一下下面這段代碼,讓你們對javapoet有一直觀的認識

MethodSpec.Builder injectMethod = MethodSpec.methodBuilder("inject")//生成一個方法,方法名是inject
        .addAnnotation(Override.class)//給方法加上"Override.class"註解
        .addModifiers(Modifier.PUBLIC)//給方法加上訪問控制符
        .addParameter(Object.class, "target")//給方法加上參數
        .addStatement("$T substitute = ($T)target", className, className);//在方法體內定義一條語名

上面的代碼生成下面的代碼(我用java代碼生成java代碼,這就是javapoet乾的事情):

@Override
public void inject(Object target) {
  MainAbility substitute = (MainAbility)target;
}

看完上面這一坨,你若是以爲難。請用JavaWriter生成java文件。你就會以爲javapoet真香。

第三步:經過模板類注入view對象

在apt-api中,咱們定義一個AutoBind.java類封裝對模板類MainAbility$$Autobind.java的操做。

按照模板類的命名規則xxx$$Autobind,經過反射實例化出MainAbility$$Autobind.java,調用 其中的inject方法,完成view的注入。

總結

apt只是一個工具,在這套工具框架下,怎麼處理註解纔是難點。

BufferKnife和咱們的「乞丐版BufferKnife」本質上沒有區別。除了注入view,還支持事件綁定、增量編譯。

 

做者:沒用的喵叔

想了解更多內容,請訪問51CTO和華爲合做共建的鴻蒙社區:https://harmonyos.51cto.com

相關文章
相關標籤/搜索