對Flutter路由管理庫Fluro的封裝

SuperMan一路向北發表於2019-09-13

在公司使用flutter開發過一個app後,我也算一個老使用者了,練習時長半年,最近公司的搞重構,要用到fluro來對路由進行管理,我們一起來簡單體驗下。

1.增加page_router.dart檔案

在這裡檔案裡面編寫下面的程式碼

對Flutter路由管理庫Fluro的封裝

一個PageRouter類,裡面我們定義靜態的fluro提供的Router例項 然後再定義個靜態方法setupRoutes,用來設定我們的routes

2.增加page_routes.dart

對Flutter路由管理庫Fluro的封裝

在這裡我定義了一個map集合,key是頁面的path,value是按照fluro的要求是一個Handler的例項

這裡注意到我們的HomePage頁面需要傳入一個userId引數,那我在這裡就要提前把它傳入進去 首先我在定義path時要注意/home是頁面的path,:userId相當於頁面url的引數,是個佔位符,一會跳轉的時候我們要傳入 比如:router.navigateTo(context, "/home/1234", transition: TransitionType.fadeIn); 另外那個params引數是個map,key就是我們左邊定義的佔位符的引數名字,但是呢,params["userId"]是個List,並沒有直接取出傳的值,我不太明白這裡為啥搞個List出來,直接給我值不行嗎?而且這個值實在List的第一個,所以我們用.first取出來

3.註冊routes

上面我們定義好了routes,但是還沒有跟fluro扯上半點關係,接下來我們把它們關聯起來

回到page_router.dart檔案 我們在setupRoutes方法裡面新增程式碼,我們先匯入page_routes.dart檔案

對Flutter路由管理庫Fluro的封裝

在setupRoutes裡面我們遍歷那個map,裡面呼叫router.define()來把路由註冊到Fluro Router。 這裡我們已經完成了大部分的工作 強調一下,在我使用fluro之前我也搜尋了相關文章,發現他們在註冊路由時都是在手動註冊,就是類似這樣的程式碼

router.define(xx, handler: xxHandler);
router.define(xx, handler: xxHandler);
複製程式碼

作為程式設計師能自動就別手動對吧,這樣的重複程式碼直接迴圈搞定就行了,也可能別人是為了演示簡單寫寫吧。

4.設定router到MaterialApp

  • 先在main.dart的入口main()方法裡面執行下面的程式碼
  PageRouter.setupRoutes();
複製程式碼

就是呼叫上面PageRouter的setupRoutes方法執行註冊routes

  • 跟MaterialApp繫結
 MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
primarySwatch: Colors.blue,
 ),
 onGenerateRoute: PageRouter.router.generator,
) 

複製程式碼

5.改進

我們回顧下第2步新增routes的時候的寫法 我感覺看起來還是不夠優雅啊

對Flutter路由管理庫Fluro的封裝

  • 都是以字串來命名路由名字,很容易起衝突導致被覆蓋,當頁面名字多的時候後面新增的頁面path容易跟上面的一樣,而且我們頁面傳的引數那個佔位符寫起來樣子怪怪的,兩三個引數下來path長長的一大堆,
  • 頁面傳引數很囉嗦,我覺得那個params設計的很不好,是個map我們取值時型別丟失,我們一眼看過去不知道到底取得什麼型別,雖然params取出來的是個List,我們可以知道是個String,但是我無法從肉眼直接看到是什麼型別,特別是當接盤俠來改程式碼時,一臉懵逼啊。型別丟失就是因為fluro內部寫死了從params取出來的都是String的值,不過可以理解,一般url傳引數也都是字串型別吧,但是比如我上面給ClassDetailPage傳id時,因為我定義的是int型別,而我通過params["id"][0]拿到的是String,我還要做個型別轉換,
  • 這串程式碼整體看起來冗餘,寫起來很麻煩

廢話說太多了,來優化一下吧 首先解決頁面之間傳值得問題,用fluro傳值需要在定義routes的地方提前寫好,我認為不太符合習慣,我的習慣是我在跳轉頁面的時候我再去組合陣列把值傳過去,現在我不僅要在定義routes的時候取值賦值,還要在跳頁面的時候再組合資料進行傳值, 這時候呢,如果你是安卓程式設計師你會不會想到Activity之間傳值得時候用到的一個叫Bundle的東西呢?沒錯,我們把它搞過來

對Flutter路由管理庫Fluro的封裝

我們使用這個有幾個好處

  • 一眼看過去能明顯知道你要從map中取得是什麼型別的值,獲取你放的是什麼型別的值
  • 我們把頁面之間要傳遞的資料通過一個Bundle物件打包傳輸,避免了我們在使用fluro時挨個從params來取引數,
  • 如果你用的key不小心寫錯了,我會丟擲異常提示,不用等到用的時候才發現是null,

看下使用效果

對Flutter路由管理庫Fluro的封裝

這樣子做,接盤俠再也不會抱怨不知道你寫的什麼型別了,上面我寫錯了型別,ide也能提示出來

接下來我們改造下fluro給頁面傳引數那裡 增加一個類

對Flutter路由管理庫Fluro的封裝

一個叫PageBuilder的類,getHandler最終返回fluro需要的handler,

下面我們來改造page_routes.dart檔案

對Flutter路由管理庫Fluro的封裝

看這裡是不是比之前清爽了很多,

  • map的key不再是字串,我們定義了一個列舉,PageName,我們知道列舉的值不能重複,當你寫重複的時候,ide直接提示出來了,這樣保證了我們不會出現像字串那樣重複
  • 我們看下map的value,是不是很清爽,沒有了之前那一大堆的東西,看下之前的

對Flutter路由管理庫Fluro的封裝

現在看的話感覺這就是坨~~~啊

優化後我們每次增加頁面只需要先增加一個頁面名稱到列舉PageName,然後再來給這個map新增key和value vlaue就直接寫

PageBuilder(builder: (bundle) => LoginPage())
複製程式碼

這裡這個bundle就是你在頁面之間傳值得bundle,你要把要傳輸的值放在這個bundle物件裡面,然後手動傳到頁面的引數裡比如這個 PageBuilder(builder: (bundle) => HomePage(bundle)) HomePage裡面我宣告瞭final Bundle bundle;

對Flutter路由管理庫Fluro的封裝

來看下我們怎麼傳值

對Flutter路由管理庫Fluro的封裝

這裡我們要用到flutter自帶的Navigator來跳轉了,Navigator.pushNamed的第二個引數是String型別,所以我們這裡對這個列舉的值進行toString一下,可以看到我們這裡直接從PageName來拿頁面名字,而不用像之前那樣自己輸入字串,很容易輸入錯誤, 再看arguments,這個引數就放我們的bundle物件,通過這個引數把bundle傳輸到下一個頁面

最後

在這裡感謝fluro作者的貢獻,大家有什麼想法可以評論留言哦,祝大家中秋節快樂!

相關文章