Flutter學習篇(六)——路由剖析終篇

導航

前言

路由剖析前篇已經講了Navigator的初始化,路由的映射生成以及觀察訂閱,這個篇章則會側重於路由的形態以及路由的本質。git

剖析

咱們仍是回到NavigatorStatepush方法,github

方法雖然不長,信息量卻很多,簡要來講,有這麼幾點:ide

  • Route
  • _history
  • return route.popped

作的事情無外乎就是從_history取出oldRoute, 把route加入_history,而後各自調用oldRoute,route的一些相似生命週期的方法, 最後返回route.poped。其中有個很特別的地方是調用了route.install(),這個咱們待會再講。post

_history

_history很好理解,它是個List,做爲棧存儲每個路由,push, pop操做分別對應Listadd,removeLast學習

Route

接着咱們看到Route這個類,鋪墊了這麼久,終於要見到路由本尊了,老規矩,先一覽全部👀。ui

Route的內置方法咱們能夠簡單分紅三類:

  1. 生命週期類型,didPop,didPush等等
  2. 狀態類型,isCurrent,isFirst,isActive
  3. install

前兩類咱們就不講了,由於知其名而知其意😎。而install就神祕的很,畢竟它就是路由的核心了,不知道讀者們有沒有發現,其實講到如今,NavigatorRoute的關聯仍是很模糊,而install將會揭開這二者之間的鮮爲人知的祕密(別問我爲何知道的這麼清楚,由於我事先看過🤣)。spa

對於install方法,其中有個很重要的類,那就是OverlayEntity, 它提供了Overlay所須要的信息,如opaque等,而Overlay如其名,是一個懸浮覆蓋的widget,因此說一個好的名字是多麼重要,相信大家也恍然大悟了吧。路由的本質就是就是把咱們的頁面包含在Overlay這個widget裏面,而後覆蓋在舊的頁面上去。因此對於彈框來講,也就很好理解了,就是把彈框放入一個透明的Overlay裏面,而後蓋在當前的頁面上面,牛逼🐮!
知道這個關聯以後,咱們下一步就是找出RouteOverlayEntity的轉換關係,咱們先從平時使用的MaterialPageRoute入手,深扒它的父類,最後在ModalRoute找到了這麼一個方法,3d

@override
  Iterable<OverlayEntry> createOverlayEntries() sync* {
    yield _modalBarrier = OverlayEntry(builder: _buildModalBarrier);
    yield OverlayEntry(builder: _buildModalScope, maintainState: maintainState);
  }
複製代碼

接着咱們順藤摸瓜,找到ModalRoute對應的build方法,看到了這麼一個關鍵:code

widget.route.buildPage 這不是擺明告訴咱們是在這裏建立的頁面嗎,而後咱們返回MaterialPageRoute,果不其然cdn

builder是咱們傳進去的生成widget的方法,在這裏生成了widget。

因此,綜上,咱們的路由頁面經過buildPage做爲widget傳遞到ModalRoute,接着在ModalRoute經過createOverlayEntries將路由頁面包裝在Overlay這個覆蓋型的widget。因此install就是這麼一個過程,它將路由頁面映射爲Overlay,而Navigator則負責管理路由的進出。

通訊

講完 install,再回過頭看看剛剛的疑問,還有一個地方沒解決的,那就是push以後的返回值route.popped, 究竟爲何須要這麼一個返回值呢?其實這就是涉及到路由之間的通訊了,當頁面退出時,能夠攜帶一些信息回到上一個頁面。以下:

能夠看到,pop方法的參數result傳遞到了didPop,那咱們繼續扒一扒didPop

這裏又發現了一個新大陸_popCompleter🙄, 它是個啥呢,官方介紹以下Completer:

A way to produce Future objects and to complete them later with a value or error.
複製代碼

它是個能夠延後執行的Future對象,那這樣一來就串起來了,路由pop以後,執行了_popCompleter的完成方法,參數天然就經過Future對象傳遞出去,上一個頁面只須要監聽_popCompleter的回調便可,這時候就輪到push以後的返回值route.popped登場了,沒錯,這個返回值就是_popCompleter的Future對象,以下:

Future<T> get popped => _popCompleter.future;
複製代碼

因此,梳理一下,當咱們push一個路由的時候,咱們會拿到下一個路由的 Future對象,當下一個路由pop的時候,Future對象就執行回調,以下:

Navigator.of(context).push(MaterialPageRoute(builder:(context) => SettingsPage()).then((value){
                    print(value);
});
複製代碼

這樣一來,咱們就能夠監聽到路由傳遞回來的值了。

路由分類

其實能夠簡單粗暴地根據opaque將路由劃分爲兩類:

  • 透明
  • 不透明

對應的其實就是彈框和頁面,對於頁面級的路由,繼承自PageRoute, 對應的opaque爲true,不透明頁面;而彈框繼承自PopupRoute, opaque爲false,透明頁面,因此呈現爲彈框的形態。

總結

其實這個篇章主要是經過深究push方法,從中窺探路由的本質,對於路由來說,追溯到底,它仍是widget,只不過藏得比較深。其實再複雜的東西,一層一層剖開,它仍然是一個系統最基本最核心的個體,這個剖析的過程尚且容易,最難的每每是從0到1,簡單到複雜,這須要極大的智慧去搭建,組裝和落地。

倉庫

點擊flutter_demo,查看完整代碼。

參考

相關文章
相關標籤/搜索