前言
結合前面的模塊之間的交互,主要分析了類加載、全局Map記錄(跳轉目標Class)兩種交互方式,以及APT和JavaPoet技術生成類文件,本文分析組件化的路由架構,我們到底需要通過APT和JavaPoet生成什麼樣的類文件呢?
組件化路由架構設計
先來看這樣一幅架構設計圖,組文件記錄是一對一的即一個子模塊對應一個組文件記錄,而一個組文件記錄對應多個路徑文件記錄,第二點比較好理解,因爲各個子模塊有多個Activity,對應多個路徑信息。對應第一點,爲什麼要生成一對一的組(名)文件記錄呢?試想一下,如果用戶進入首頁,沒有進行後續操作,退出應用。而我們還像之前分析的,在application中將全部的activity對應的路徑信息記錄到Map集合,加載到內存,這顯然是不合理的,出於性能優化(內存優化)的考慮,只有用到對應組(模塊)時,纔去保存對應模塊下Activity的路徑信息。所以纔會根據組(模塊)名,生成對應的文件記錄。要通過APT和JavaPoet生成哪些類文件呢?
RouterBean對象
在前面的文章中通過全局Map記錄方案實現子模塊交互時,有涉及到PathBean對象,主要包含目標Activity的路徑path,和Class屬性。獲取class屬性,即可實現交互(跳轉)。而RouterBean對象就是在PathBean的基礎上進行了擴展:
public class RouterBean {
// 枚舉,現在只是處理作用在Activity上的註解
// 後續還會擴展處理接口上的註解
public enum Type{
ACTIVITY
}
//枚舉類型
private Type type;
//類節點
private Element element;
//路由的組名
private String group;
//路由的地址
private String path;
//被@ARouter註解的類對象
private Class<?> clazz;
private RouterBean(Builder builder) {
this.type = builder.type;
this.element = builder.element;
this.clazz = builder.clazz;
this.path = builder.path;
this.group = builder.group;
}
...
}
Element類節點爲什麼也要存起來?
- 因爲將來我們要在註解處理器中,循環拿到每個類節點,方便賦值和調用
- Element它是javax.lang包下的,不屬於Android Library
ARouterLoadGroup接口
/**
* 路由組group對外提供加載數據接口
*/
public interface ARouterLoadGroup {
/**
* 加載路由組group數據
* 比如:"app", ARouter$$Path$$app.class(實現了ARouterLoadPath接口)
* @return key: "app"即組名, value: "app"分組對應的路由詳細對象類
*/
Map<String, Class<? extends ARouterLoadPath>> loadGroup();
}
Map<String, Class<? extends ARouterLoadPath>>
- 需要生成路由路徑文件後,才能生成路由組文件
- 接口方式容易拓展、通用
ARouterLoadPath接口
/**
* 路由組group對應的詳細path加載數據接口
* 比如:app分組對應有哪些類需要加載
*/
public interface ARouterLoadPath{
/**
* 加載路由組group中的path詳細數據
* 比如:app分組下有這些信息
* @return key: "app/MainActivity", value:MainActivity信息封裝到RouterBean對象中
*/
Map<String, RouterBean> loadPath();
}
Map<String, RouterBean>
- OOP思想,讓單純的targetClass變成更靈活的RouterBean對象
- 接口方式容易拓展、通用
路由框架部署步驟
- 配置arouter_api/build.gradle
- 配置common(公共基礎庫)/build.gradle
- 完成模擬APT生成的類代碼
- app子模塊中,模擬跳轉代碼
- 演示跳轉
相關的配置問題可以參考前面的文章和文末代碼鏈接查看。這裏重點介紹模擬生成的類文件中的邏輯,以及跳轉邏輯。在app模塊中新建一個目錄test,存放模擬apt生成的文件,就是自己手動創建的,主要是爲了對流程進行說明,後續會通過apt來生成文件。不同模塊對應文件中的邏輯是一樣的
/**
* 模擬ARouter路由器的組文件
*/
public class ARouter$$Group$$order implements ARouterLoadGroup {
@Override
public Map<String, Class<? extends ARouterLoadPath>> loadGroup() {
// key: 組名,value: 分組對應的路由詳細對象類
Map<String, Class<? extends ARouterLoadPath>> groupMap = new HashMap<>();
groupMap.put("order", ARouter$$Path$$order.class);
return groupMap;
}
}
返回的是map集合,key表示組名比如order,value表示分組(即模塊)對應路由詳細對象類
/**
* 模擬ARouter路由器的組文件對應的路徑
*/
public class ARouter$$Path$$order implements ARouterLoadPath {
@Override
public Map<String, RouterBean> loadPath() {
Map<String, RouterBean> pathMap = new HashMap<>();
pathMap.put("/order/Order_MainActivity",
RouterBean.create(RouterBean.Type.ACTIVITY, Order_MainActivity.class,
"/order/Order_MainActivity", "order"));
return pathMap;
}
}
返回的是map集合,key表示路徑信息,value表示將目標Activity的信息封裝到RouterBean對象,可以從中獲取對應的class對象。如果這部分不是很理解,看了跳轉邏輯,應該就比較清晰了。
在app的MainActivity中,跳轉邏輯如下:
public void jumpOrder(View view) {
/*Intent intent = new Intent(this, OrderActivity.class);
intent.putExtra("name", "xpf");
startActivity(intent);*/
// 模擬APT生成的類文件,實現跳轉
ARouterLoadGroup loadGroup = new ARouter$$Group$$order();
// 只會加載order模塊Activity對應的類對象到內存,避免將所有模塊的Activity對應的類對象加載到內存
// 這就是處於性能優化(準確的說是內存優化),要有分組保存、獲取的原因
Map<String, Class<? extends ARouterLoadPath>> groupMap = loadGroup.loadGroup();
// app--->order
Class<? extends ARouterLoadPath> clazz = groupMap.get("order");
try {
ARouterLoadPath path = clazz.newInstance();
Map<String, RouterBean> pathBean = path.loadPath();
// 獲取/order/OrderActivity
RouterBean routerBean = pathBean.get("/order/OrderActivity");
if (routerBean != null) {
Intent intent = new Intent(this, routerBean.getClazz());
intent.putExtra("name", "xpf");
startActivity(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
首先實例化路由組文件,調用loadGroup方法獲取保存的order模塊的路徑文件,通過它可以獲取order模塊Activity對應的類對象即class對象,然後實現跳轉。如註釋處所描述的,此時personal模塊的所有Activity對應的類對象都不會加載到內存,這就是在性能方面的一個小優化,準確的說是內存優化。如果模塊越多,每個模塊的Activity越多,這個優化的作用就明顯。只有需要進行跳轉的時候,纔會去加載對應模塊Activity的類對象。
效果演示:
本文分析組件化的路由架構思路,也就是我們要通過APT生成什麼樣的文件,並手動實現演示可行性。下一篇將分析通過APT生成具體相關路由的類文件來實現。
代碼鏈接:https://github.com/xpf-android/Moudlar_ARouter