1. 程式人生 > >APP開發實戰61-Activity訊息路由

APP開發實戰61-Activity訊息路由

16.2Activity訊息路由

在Android開發中,常遇到多個Activity間的相互通訊和呼叫,這樣會導致Acticity間的橫向依賴。

(轉自:

Android中,開啟頁面的方式主要是startActivity()。使用startActivity()的缺點是需要開啟的那個Activity的類已經存在,否則無法通過編譯,但是在協同開發中,這往往是無法得到滿足的。為了解決此問題,需要在Android平臺設計和實現一個路由框架。

16.2.1框架整體設計

首先我們需要明確一點,那就是我們的框架不能僅僅侷限於開啟Activity,開啟Activity只是框架中的一種行為實現,我們的框架應該是包含了Activity以及其它比較常用的路由。並支援使用者自己新增自己的路由實現的,如使用者希望使用url呼叫一個方法,或者呼叫一個Runnable,那麼他就可以自己實現一個Router來支援這種行為。基於這樣的思路,路由框架的整體架構設計如下。

在以上框架中,由RouterManager維護所有的IRouter列表。我們的框架自身實現了開啟Activity的ActivityRouter。同時使用者可以新增自己的IRouter實現。當用戶想要開啟某個url時,呼叫RouterManager的open()方法,RouterManager遍歷列表,呼叫IRouter的canOpenTheUrl方法找到第一個能夠開啟該url的IRouter,並將該open的任務dispatch給該Router。 但是在分析實際使用情景中,我們發現這樣的框架設計並不能滿足實際使用需求,主要有如下幾點。

(1)在開啟Activity可能需要設定動畫。

(2)需要選擇使用startActivityForResult()來開啟Activity。

(3)需要傳遞一些無法放到url中的傳遞引數,如Parcelable等。

    雖然這僅僅是ActivityRouter的需求,但我們也需要讓我們的框架支援這些。因此,我們對以上框架設計做了一些修改如下:

使用者在需要額外設定一些引數的時候可以不選擇使用open開啟url,而是使用getRoute()方法獲得抽象的Route物件,通過Route物件進行額外的設定,最後可以通過IRoute介面的open方法開啟它自己。IRouter和IRoute的關係應該是一對一或者一對多,一種IRouter應該可以開啟一或者多種不同IRoute。而一個IRoute則一般只能由一種IRouter開啟。

16.2.2路由格式

在路由框架中,url應該包含兩點功能,一是唯一確定一條路由,二是提供一些引數。我們可以以一個路由的例子來講解ActivityRouter的路由規則。本規則參考了REST。 
例:activity://main/:i{key1}/path1/:f{key2}

scheme為activity代表該url可以被ActivityRouter開啟。

host為main一般表示決定的Activity。

而:{key1}則表示一個值的key,這個path segment在url中會被具體的值替換,:後面的i表示該key對應的值的型別為int型。

path1為固定的path segment,與上面的key用來傳遞值不同。用來區分路由,與host功能類似。

因此一個url與路由匹配需要scheme,host以及path中的固定部分相同,而key部分被具體的值代替。

以下舉一個匹配上面的路由的url的例子:

activity:main/123/path1/12.4。

則會呼叫intent的putExtra()方法將key1=123,key2=12.4放到intent的bundle中。在被跳的Activity中就可以獲取對應的值。如果有些值是不必須的,已可以放到queryparameter中。如activity://main/123/path1?des=hello。但query parameter不影響路由匹配。

16.2.3路由表的初始化

Router需要提供一個方法讓使用者初始化路由表。如下ActivityRouter的實現,當然這並不必要,如開啟網頁的Router就不需要路由表,只需要呼叫系統瀏覽器開啟網頁即可。所以該方法沒有在介面中定義。

       public void init(Context appContext,IActivityRouteTableInitializer initializer) {

       mBaseContext = appContext;

       initializer.initRouterTable(mRouteTable);

    }

publicinterface IActivityRouteTableInitializer {

    /**

     * init the router table

     * @param router the router map to

     */

    void initRouterTable(Map<String,Class<? extends Activity>> router);

}

16.2.4總結

將原本startActivity方式替換成路由方式後,有以下幾個明顯的優點。

(1)便於協同開發

(2)便於測試,可以在測試中替換一個路由表,開啟測試用Activity。

(3)便於從外部連結跳轉到app中的任意介面。我們只需要設定一個外鏈入口Activity,讓其接收外部連結,並呼叫路由管理器開啟該連結即可。

專案地址: