Router(三):自定義XML協議

前言

之前我們把ARouter的原理分析了一遍,如果你是剛啓動的新項目,建議立刻使用,哪天運營有這個需求了,你就可以牛逼的對他說,我早就已經做好了。

但是老項目就會有一丟丟的尷尬,所以我們要在ARouter的基礎上,獨立深度鏈接的功能,然後打造出加強版的深度鏈接庫,我起名爲DeepLinkSo。

正文

回顧一下ARouter的源碼,我們記得他使用的是自定義註解,完成路由的註冊和綁定。註解看上去高大上,但是在這裏我認爲存在一個致命的短板,那就是不夠靈活

註解的侷限性

註解的解析是在編譯期間完成並生成源碼,也就是說版本一經發布,註冊的路由地址就無法發生改變,例如

  1. 開啓新的路由。例如個人信息頁我們並沒有配置路由,我們就無法通過深度鏈接打開這個網頁,只能修改代碼,然後重新發布版本解決這個問題。
  2. 關閉某個路由,因爲某些原因某個頁面要停止外部訪問,也只能修改代碼,然後重新發布版本。

所以幾經思考,如果路由的配置文件能夠從網上下載更新的話,是不是就能讓深度鏈接更佳靈活呢?

於是我選擇了使用XML。
使用註解可以在編譯期間生成源碼,節省了啓動時間,但是犧牲了靈活性。
使用XML恰恰相反,沒有增加編譯時間,而是增加了啓動時間,但是我們的XML還是很小的,經過測試也就10毫秒左右,還在可以接受的範圍內。

自定義XML協議

XML協議無論在前端後端都被廣泛的使用,而且Android對XML解析的有很好的支持,複習一下XML解析的三種方式:

1、SAX解析
2、Pull解析(推薦)
3、Dom解析

Android推薦使用Pull解析,輕量快速,所以我們也選擇使用Pull解析。

首先制定好我們的XML格式:

<?xml version="1.0" encoding="utf-8"?>
<DeepLinkSo>

    <!-- 版本號 -->
    <version value="1" />

    <!-- 攔截器會按照配置的順序依次執行 -->
    <common-interceptors>
        <common-interceptor>com.lzp.deeplinkso.demo.interceptor.TestInterceptor</common-interceptor>
    </common-interceptors>

    <!-- 所有需要支持DeepLink的文件列表 -->
    <list>

        <!-- 跳轉的頁面 -->
        <Activity>
            <class>com.lzp.deeplinkso.demo.MainActivity</class>
            <page>main</page>
        </Activity>

        <!-- 跳轉的頁面 -->
        <Activity>
            <class>com.lzp.deeplinkso.demo.TestActivity</class>
            <page>test</page>
            <!-- 需要的參數 -->
            <params>
                <key type="Long" value="userId" />
                <key value="userName" />
            </params>
            <!-- 是否跳過公共Interceptor -->
            <skipCommonInterceptor>true</skipCommonInterceptor>
            <!-- 私有攔截器 -->
            <!--<interceptors>-->
                <!--<interceptor>com.lzp.deeplinkso.demo.interceptor.TestInterceptor</interceptor>-->
            <!--</interceptors>-->
        </Activity>

        <!-- 自定義事件 -->
        <Event>
            <class>com.lzp.deeplinkso.demo.handler.TestEventHandler</class>
            <page>event</page>
            <params>
                <key value="eventId" />
            </params>
        </Event>

    </list>

</DeepLinkSo>

我們在XML制定了以下內容:

1、版本號。可以根據降級和升級做一些操作。
2、全局攔截器。所有的跳轉都會經過攔截處理,我們可以在跳轉中設置跳過全局攔截器。
3、跳轉的頁面。可以設置對應的路由地址,跳轉的參數,私有攔截器等。
4、自定義事件。設置和頁面是一樣的,只是不跳轉頁面。

這樣我們的功能已經算是很全面了,接下來我們可以通過解析XML,保存所有的配置信息:

class DeepLinkSoConfig {

    /**
     * 當前版本號
     *
     *  無實際作用,僅僅是爲了區別xml的版本
     * */
    private var version = "0"

    internal var listener: IDeepLinkSoListener? = null

    /**
     * 保存跳轉Activity配置項
     * */
    private val activityOptionMap = HashMap<String, DeepLinkSoActivityOption>()

    /**
     * 保存自定義事件配置項
     * */
    private val eventOptionMap = HashMap<String, DeepLinkSoEventOption>()

    /**
     * 自定義攔截器
     * */
    internal var interceptors: ArrayList<IDeepLinkSoInterceptor>? = null

    internal fun setVersionCode(version: String) {
        this.version = version
    }

    fun getVersionCode() = this.version

    /**
     *  添加配置項
     * */
    internal fun addOption(key: String, option: DeepLinkSoOption) {
        when (option) {
            is DeepLinkSoActivityOption -> activityOptionMap[key] = option
            is DeepLinkSoEventOption -> eventOptionMap[key] = option
        }
    }

    /**
     *  添加配置項
     * */
    internal fun getOption(key: String): DeepLinkSoOption? {
        return activityOptionMap[key] ?: eventOptionMap[key]
    }

    /**
     *  獲取Activity配置項
     * */
    internal fun getActivityOption(key: String) = activityOptionMap[key]

    /**
     *  獲取Event配置項
     * */
    internal fun getEventOption(key: String) = eventOptionMap[key]

    /**
     * 清除配置項
     * */
    internal fun reset() {
        activityOptionMap.clear()
        eventOptionMap.clear()
        interceptors?.clear()
    }

}

解析的過程就不貼了,到此爲止,我們已經爲具體的開發做好了準備。

總結

今天我們分析了並制定了深度鏈接庫的XML協議,思考了使用註解和XML的優劣點,爲之後的功能開發做好準備。

 

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