Android組件化實戰六:路由架構設計

前言

結合前面的模塊之間的交互,主要分析了類加載、全局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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章