WMRouter-基本結構分析
文章是作者學習 WMRouter
的原始碼的重點紀要。 WMRouter官方文件 : ofollow,noindex">https://mp.weixin.qq.com/s/pKRi5qpZmol7xFIfeBbK_A
本文整理一下 WMRouter
的基本路由邏輯,並剖析相關路由類的設計。作者巧妙的使用繼承設計了整個 WMRouter
的路由體系,下面我們就從原始碼來看一下是如何實現的:
UriHandler
在 WMRouter
中,對於每一個或每一類 Uri
都會有一個 UriHandler
來做處理,這個類定義了一個基本的處理邏輯。
該類處理 Uri
的入口方法為 handle
, 因此,理清它的主要處理邏輯,我們只需要看這個方法即可:
//處理URI。通常不需要覆寫本方法。 public void handle(@NonNull final UriRequest request, @NonNull final UriCallback callback) { if (shouldHandle(request)) { if (mInterceptor != null && !request.isSkipInterceptors()) { mInterceptor.intercept(request, new UriCallback() { @Override public void onNext() { handleInternal(request, callback); } @Override public void onComplete(int result) { callback.onComplete(result); } }); } else { handleInternal(request, callback); } } else { callback.onNext(); } }
mInterceptor
為 ChainedInterceptor
的例項,下面會介紹。
handle()
具體處理邏輯如下圖:

UriHandle.handle().png
UriInterceptor 與 ChainedInterceptor
UriInterceptor
為設定給 UriHandler
的攔截器,在 handleInternal
方法之前呼叫。
public interface UriInterceptor { void intercept(@NonNull UriRequest request, @NonNull UriCallback callback); }
UriHandler
中的攔截器是 ChainedInterceptor
, ChainedInterceptor
實現了 UriInterceptor
, 並含有一個 UriInterceptor
列表,即支援新增多個攔截器,來看一下核心實現:
public void intercept(@NonNull UriRequest request, @NonNull UriCallback callback) { next(mInterceptors.iterator(), request, callback);//對於鏈上的每一個 interceptor 都要呼叫一遍 } private void next(@NonNull final Iterator<UriInterceptor> iterator, @NonNull final UriRequest request, @NonNull final UriCallback callback) { if (iterator.hasNext()) { iterator.next().intercept(request, new UriCallback() { @Override public void onNext() { next(iterator, request, callback); } @Override public void onComplete(int resultCode) { callback.onComplete(resultCode); } }); } else { callback.onNext(); } }
即,依次遍歷每一個 UriInterceptor
,呼叫其 intercept
方法。需要注意的是 callback.onComplete(resultCode)
的呼叫,會導致路由的終止。
ChainedHandler
上面 UriHandler
是處理一個uri的hanler,比如 A Activity的路由為 test://a
,那麼可以新建一個 UriHandler
來處理,而 ChainedHandler
則以列表組織多個 UriHandler
,每向 ChainedHandler
插入一個 UriHandler
可以指定一個優先順序,優先順序高的會被插入到列表前面。 ChainedHandler
複寫了 handleInternal
方法:
@Override protected void handleInternal(@NonNull final UriRequest request, @NonNull final UriCallback callback) { next(mHandlers.iterator(), request, callback); } private void next(@NonNull final Iterator<UriHandler> iterator, @NonNull final UriRequest request, @NonNull final UriCallback callback) { if (iterator.hasNext()) { UriHandler t = iterator.next(); t.handle(request, new UriCallback() { @Override public void onNext() { next(iterator, request, callback); } @Override public void onComplete(int resultCode) { callback.onComplete(resultCode); } }); } else { callback.onNext(); } }
即 ChainedHandler
會逐一呼叫每個 UriHandler
的 handle
方法。
上面我們瞭解了 WMRouter
中路由的基本組成元素 UriHandler
、 UriInterceptor
、 ChainedHandler
、 ChainedInterceptor
, 接下來我們看下原始碼是如何使用它們構造路由體系的:
RootUriHandler
它繼承自 ChainedHandler
,提供 startUri(UriRequest)
並傳入 RootUriCallback
來作為一次路由的起點:
public void startUri(@NonNull UriRequest request) { //刪除了一系列的判斷條件 handle(request, new RootUriCallback(request)); } protected class RootUriCallback implements UriCallback { private final UriRequest mRequest; public RootUriCallback(UriRequest request) { mRequest = request; } @Override public void onNext() { onComplete(CODE_NOT_FOUND); } @Override public void onComplete(int resultCode) { switch (resultCode) { case CODE_REDIRECT:// 重定向,重新跳轉 startUri(mRequest); break; case CODE_SUCCESS: mRequest.putField(UriRequest.FIELD_RESULT_CODE, resultCode); onSuccess(mRequest); break; default: mRequest.putField(UriRequest.FIELD_RESULT_CODE, resultCode); onError(mRequest, resultCode); break; } } }
基於上面的設計,在 WMRouter
中路由的起點 UriHandler
為 DefaultRootUriHandler
,這個 UriHandler
在起始時添加了下面4個子Handler:
public DefaultRootUriHandler(Context context,@Nullable String defaultScheme, @Nullable String defaultHost) { // 處理RouterPage註解定義的內部頁面跳轉 addChildHandler(createPageAnnotationHandler(), 300); // 處理RouterUri註解定義的URI跳轉,如果註解沒定義,繼續分發到後面的Handler addChildHandler(createUriAnnotationHandler(defaultScheme, defaultHost), 200); // 處理RouterRegex註解定義的正則匹配 addChildHandler( createRegexAnnotationHandler(), 100); addChildHandler(new StartUriHandler(), -100); }
這幾個子 UriHandler
當然也是繼承自 UriHandler
, 對於每一個子Handler,下一節再分析。
經過上面的分析,我們大致可以總結 WMRouter
的路由過程:

WMRouter路由體系.png
讀後感
可以看到作者基本上使用兩個概念 UriHandler
和 UriInterceptor
就完成了整個設計。並再此基礎上引入了 ChainedHandler
和 ChainedInterceptor
,整體設計十分巧妙。
不過說實話,我在第一遍閱讀這部分原始碼的時候 ChainedHandler
與 UriHandler
把我攪的是有點小頭暈的。我想可能另一種設定思路如下:

我想象的組成結構WMRouter.png