看了一篇關(guān)于移動端路由的文章一步步構(gòu)建iOS路由, 感覺寫的多, 寫的也很好, 所以我決定去看看源碼, 在用我自己的語言來重新總結(jié)一下.
其實說到路由, 不由得就想起了組件化, 但是這兩者是有本質(zhì)化區(qū)別的, 路由只是實現(xiàn)組件化甚至插件化的一種手段而已, 作者之前也寫過一篇關(guān)于組件化的文章, 就不多說了.
路由的作用在我看來就是把 任務/行為 都封裝成一個一個請求,或者我們稱之為任務. 然后由路由器統(tǒng)一管理和處理, 從而就可以很好地監(jiān)聽任務的執(zhí)行.
其實更極端點的說法就是路由器就是一個任務調(diào)度中心, 我們可以獲取整個任務的前因和后果, 其實這里是一個打印 log 的好地方, 集中處理記錄所有的行為. 當然我們?nèi)绻ㄟ^中間件這種方式來操作.
大家可以先看看原作者的博文, 再來看我這個狗尾續(xù)貂之作.
簡單說一下路由器的工作流吧
- 首先我們獲取到一個 url, 可以是 內(nèi)部調(diào)用 也可以是外部調(diào)用,
https://www.abc.com/123
,action://doSomething
這其中包括兩個部分 scheme 和 path, 我們在適配的時候會根據(jù)這兩部分得到對應的 handler - 我們向路由器根據(jù) url 注冊 handler 和 blockHandler, 這里的 url 支持正則和如有參數(shù), 以代碼中的例子
[self.router registerHandler:[[WLRSignHandler alloc]init] forRoute:@"/signin/:phone([0-9]+)"];
- 我們還可以設置一些滿足 WLRRouteMiddleware 協(xié)議的中間件, 來處理和終止我們的每次 request
- 之前都是一些配置工作,現(xiàn)在我們開始正式的工作流
- WLRRouter 去 handler 對應的 url, 如果 被適配器 WLRRouteMatcher適配到, 則生成對應的 WLRRouteRequest, 否則結(jié)束任務.
- 用所有的中間件依次處理 WLRRouteRequest, 發(fā)生錯誤或者任務被中間件中斷則結(jié)束
- 找到對應的 handler 來執(zhí)行 WLRRouteRequest
更細節(jié)的東西我建議大家去看源碼,或者 WLRRoute 作者的博客.
一些思考和改善
首先說現(xiàn)在的功能其實已經(jīng)可以滿足大多數(shù)的使用場景, 但是如果我們把路由看做一個功能強大的任務調(diào)度中心的話, 那么就引出了下面的我的一系列思考和問題.
具體的解決方案我就不說了, 我希望大家自己想一下, 我提出的這些問題是否是有必要的, 如果有必要, 應該如何設計代碼?
中間件的優(yōu)化?
目前的中間件能做的事情就是在任務開始之前得到 request , 然后進行操作, 可以返回結(jié)果結(jié)束任務, 或者直接拋出錯誤.
但是, 我們的任務不僅僅是推出一個新的界面的話, 如果也包括執(zhí)行一段邏輯的話, 那么是否中間件也要對 request 的 reponse 進行處理呢? 比如判斷邏輯執(zhí)行的效率, 計算執(zhí)行時間等等.
在我的想法中, 中間件是這么執(zhí)行的, 感覺可以做很多事情的樣子
- Middleware1
- Middleware2
- handler
-Middleware2
- Middleware1
任務異步執(zhí)行?
其實現(xiàn)在作者是有任務執(zhí)行的, 是使用 block 的時候, 但是在我看來其實都不應該分 block 和 handler, 應該都封裝成 handler, 換句話暴露在外面的 block 接口只是一個語法糖, 里面改成 同時支持同步和異步執(zhí)行的 handler
添加上下文 Context?
移動端路由一個很大的不同就是傳遞參數(shù)比較糾結(jié), 如果只通過 url, 我們只能傳遞一些字符串參數(shù), 不能傳遞對象. 尤其是在 app 內(nèi)喚起路由的時候, 往往傳遞對象參數(shù)是一個很重要的需求.
慶幸的是,我們的請求被封裝成了 WLRRouteRequest, 那么是否可以讓這個對象持有這些參數(shù), 在 handler 中直接讀取呢?
那么繼續(xù)想下去, 我們其實有可能在處理任務的時候需要很多參數(shù),有些參數(shù)可能是一些環(huán)境參數(shù),把所有東西都放到 request 中? 我在想, 是否可以給每個 request 創(chuàng)建 一個 context, 然后把這些參數(shù)都賦值給 上下文呢
所有請求都使用統(tǒng)一的中間件?
目前, 我們的所有中間件都是全局的, 但是可能我你需要所有請求都執(zhí)行對應的中間件呢?
我其實期望的是可以針對對應的適配器添加對應的中間件, 比如我有一些任務是對數(shù)據(jù)庫的操作, 那么我系網(wǎng)針對這些任務添加記錄時間的中間件.
組適配器?
如果我們有幾個任務的 url 的前綴相同, 我們是否可以先通過前綴得到一個
WLRGroupRouteMatcher, 然后再一一添加子適配器的 handler, 我認為這樣的話可能邏輯更清晰, 而且可以做很多封裝, 把復雜的需要重復添加事情放到這里面.
適配器的效率問題?
現(xiàn)在庫中的適配器是每次遍歷, 那么當適配器很多的時候, 肯定會發(fā)生效率問題, 那么我們是否可以根據(jù) scheme, 前綴, 某一個通用參數(shù)甚至是傳進來一個參數(shù)來提高我們適配的效率呢
異步的優(yōu)化?
如果我們添加了很多異步 handler, 有兩個問題必然會出現(xiàn)
1 異步的調(diào)度, 我們需要使用 NSOperation 或者 GCD
2 在一個異步路由任務中創(chuàng)建了一個新的異步路由任務
結(jié)語
好吧,好吧,我都知道,我們在移動端可能根本就不需要一個這么復雜的路由器.
這個聽著更像是一個后端的網(wǎng)絡框架的雛形.
但是我想說的是, 閑著也是閑著, 隨便瞎想想唄.