APT,就是Annotation Processing Tool 的簡稱,就是可以在程式碼編譯期間對註解進行處理,並且生成Java檔案,減少手動的程式碼輸入。一些大名鼎鼎的框架如 Retrofit, Arouter 都運用了 APT 技術。
在本片文章中我們將利用 APT 技術實現類似 ARouter 的路由功能.
不多說,先附上本文中的程式碼地址:APTdemo
實現效果
常用的 Activity 跳轉方式:
startActivity(new Intent(MainActivity.this, TwoActivity.class));
複製程式碼
我們希望通過以下方式達到 Activity 跳轉的目的:
SRouter.getInstance().navigate(MainActivity.this, "router_two");
複製程式碼
註解
建立annotation
library, 首先我們在 library 中定義註解,通過它我們可以找到哪些 Activity 需要新增到路由中
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Router {
String name();
}
複製程式碼
註解處理器 - compile
建立compile
library,依賴 annotation
模組, 注意建立的時候選擇 java-libray, 建立RouterProcessor
類繼承自 AbstractProcessor。我們需要實現 4 個方法,前3個方法簡單的寫法很固定,簡單講一下他們的作用吧;
- init()方法可以初始化拿到一些使用的工具,比如檔案相關的輔助類 Filer;元素相關的輔助類Elements;日誌相關的輔助類Messager;
- getSupportedSourceVersion()方法返回 Java 版本;
- getSupportedAnnotationTypes()方法返回要處理的註解;
其中最核心的是 process()
方法,通過javapoet 再結合註解我們就可以成相應的類。 最終我們希望生成的類是這樣的:
public final class Router$$GroupApp implements IRouterGroup {
private Map<String, String> routeMap = new HashMap();
public Router$$GroupApp() {
this.routeMap.put("router_two", "com.slyser.aptdemo.TwoActivity");
}
public String getActivityName(String routeName) {
return null != this.routeMap && !this.routeMap.isEmpty() ? (String)this.routeMap.get(routeName) : "";
}
}
複製程式碼
實現程式碼並不複雜,就是寫起來很繁瑣,還好 javapoet 為我們省了不少事。
註冊註解處理器
編譯的時候 JVM
怎麼找到我們自定義的註解處理器?這個時候就要用到 SPI
機制。簡單的用法就是在 compile
模組下新建 resources/META-INF/services 檔案,建立這個檔案很容易出錯,大家可以使用 google 出品的 auto-service
,通過註解就可以很方便的問我們建立相應的檔案
新增
auto-service
的 gradle 依賴:implementation 'com.google.auto.service:auto-service:1.0-rc3'
核心庫 - api
建立 api
library, 該庫很簡單,就只有 SRouter
一個類,核心就是反射建立註解處理器生成的物件,拿到 Activity 的 Class,完成 activity 的跳轉.
使用
在 Activity 上新增註解
@Router(name = "router_two")
public class TwoActivity extends AppCompatActivity
複製程式碼
跳轉
SRouter.getInstance().navigate(this, "router_two");
複製程式碼
這樣一個簡單的路由跳轉就完成了
總結
APT
技術其實就是自定義註解和註解處理器,在編譯期間生成Java檔案,類似於IOC控制反轉,可以方便的進行解耦,在多模組開發時可以基於APT技術構造一套路由框架,去除startActivity等造成的類依賴。