ARouter 源碼淺析第二篇

請參考ARouter源碼淺析android

服務管理

依賴注入

經過依賴注入的方式咱們能夠像上一篇文章中獲取跳轉參數同樣獲取服務,具體的實現咱們仍是經過源碼來看一下吧。 當咱們隊一個自定義的service標註上@Autowired註解的時候,從新編譯之後,APT會爲咱們自動生成以下代碼: bash

image.png
至於inject方法在哪被調用上一篇文章已經分析過了,這裏能夠看到服務的注入跟參數的注入仍是有區別的,具體的實現是插件幫咱們作了,我節選了一點代碼添上以下:
image.png
注意我圈出來的代碼,這裏區分了服務和普通類型分別生成不一樣的代碼。而服務內部注入的實例仍是經過普通方式獲取的,也就是我下面要分析的第二種獲取服務的方式。

普通方式

image.png
普通方式也分爲2種,一種是根據name,另外一種就是根據type。 下面只分析第一種根據name來獲取服務的方式,由於根據type來獲取實例是差很少的。 ###_ARouter#_navigation

private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        final Context currentContext = null == context ? mContext : context;

        switch (postcard.getType()) {
            case ACTIVITY:
                ……
                break;
            case PROVIDER:
                //注意這行代碼
                return postcard.getProvider();
            case BOARDCAST:
            case CONTENT_PROVIDER:
            case FRAGMENT:
                Class fragmentMeta = postcard.getDestination();
                try {
                    Object instance = fragmentMeta.getConstructor().newInstance();
                    if (instance instanceof Fragment) {
                        ((Fragment) instance).setArguments(postcard.getExtras());
                    } else if (instance instanceof android.support.v4.app.Fragment) {
                        ((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
                    }

                    return instance;
                } catch (Exception ex) {
                    logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
                }
            case METHOD:
            case SERVICE:
            default:
                return null;
        }

        return null;
    }
複製代碼

最後會根據postcard.getType()類型來匹配PROVIDER,而後返回provider實例,而provider的set是在LogisticsCenter#completion中: app

image.png
好了,實例獲取到了其餘的也就沒什麼好分析的了。 這裏提醒一下, 根據type來獲取實例有侷限性,只支持全局只有一個實現了相應接口的實現類,不然獲取到的實例是系統掃描到的實現最後一個實例,同上一篇文章的PathReplaceService

WHY:那爲何根據type和根據那麼來獲取實例會有區別呢?經過源碼咱們發現type是從providersIndex Map中去獲取實例的,而name是從providers Map中去獲取實例的框架

相信到這你們應該已經明白了吧。 ide

image.png

攔截器

咱們在實現攔截器的時候須要實現IInterceptor,而IInterceptor也實現了IProvider,因此IInterceptor也是一個服務。因此interceptor的實例獲取方式也是跟普通的service是同樣的,這裏不作分析。 post

image.png
對應上文的普通服務。 下面讓咱們來找一下具體獲得攔截邏輯是在哪實現的呢?請看下面的代碼:

InterceptorServiceImpl#_excute

InterceptorServiceImpl屬於arouter核心服務類 ui

image.png

InterceptorServiceImpl#doInterceptions

image.png

_ARouter#navigation

image.png
到這又回到咱們上一篇文章頁面跳轉主流程的邏輯,他其實就是在真正跳轉以前,先判斷有沒有符合的攔截器,有的話則先進行攔截器裏的操做。這裏要注意一點的是: 攔截器是有優先級的,按照priority排序,priority越小優先級越高。這是由於 interceptorsIndex的類型是TreeMap,他具備如下兩條特性:

一、TreeMap如不指定排序器,默認將按照key值進行升序排序,若是指定了排序器,則按照指定的排序器進行排序。 二、具體的排序規則,開發人員能夠在int compare()方法中進行指定。spa

image.png
到此,攔截器的實現原理咱們也就分析清楚了。

降級策略

咱們知道使用系統自帶的StartActivity()啓動後就沒法插手其中任何環節了,只能交給系統管理,這就致使了在跳轉失敗的狀況下沒法降級,而是會直接拋出運營級的異常,甚至致使崩潰,這個給用戶的感受就不是很好。因此ARouter就爲咱們提供了降級策略,主要分爲2中方式,單獨降級和全局降級(demo中這樣稱呼的)。插件

單獨降級(接口回調)&全局降級

以下代碼所示: 設計

image.png

主要回調的就是onLost,那它又是在何時才被調用的呢?咱們看以下代碼

image.png
它在completion中主動拋出異常被捕獲時調用的,若是callback不爲null就會被調用,由此也能夠看出單獨降級的優先級是高於全局降級的,else中的代碼就是全局降級的代碼。使用方式也跟普通的服務是同樣的這裏就不分析了。 咱們再看看LogisticsCenter.completion這個方法,這個是與編譯期間生成的映射文件直接打交道的模塊。先在加載到內存的節點倉庫中查找是否有該目標節點的存在,沒有就到組倉庫中找,找不到就報錯NoRouteFoundException,這就到了咱們上面的邏輯中。

LogisticsCenter#completion

public synchronized static void completion(Postcard postcard) {
        if (null == postcard) {
            throw new NoRouteFoundException(TAG + "No postcard!");
        }

        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
        if (null == routeMeta) {    // Maybe its does't exist, or didn't load.
            Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());  // Load route meta.
            if (null == groupMeta) {
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
            }
        }
}

複製代碼

#總結 通過兩篇文章,咱們基本上已經把ARouter的主要功能都分析了。其實看着很神奇的功能,只要咱們深刻到源碼裏就會發現其實也就那麼回事。不過咱們仍是能從優秀獲得框架中學到不少優秀的設計思想和前沿的技術的,好比IOC、APT, AOP等。

相關文章
相關標籤/搜索