Flutter 中用 Template Method 建構 UI 和 Bloc 做出 Reusable Widget — 小女Android 工程師實驗筆記

Chloe Hsu
Flutter Taipei
Published in
7 min readJul 7, 2019

每次刻 UI 的時候,是不是很常遇到相似的設計用在不同的頁面?或是同樣的設計用在同個頁面但是不同區塊?

每次看到這樣的設計時,就不禁手癢頭癢地想要做個可複用的 Widget 以達到可複用性、好維護性以及擴充性等等

這篇想分享最近在工作上用 Flutter 刻 UI 和做功能時的做法,以做出可複用的 Widget 和 Bloc

Let’s begin !

分析了解需求

UI

就 UI 來說,這兩個設計圖除了標題和副標題之外,其他幾乎長得一模一樣。都是一個 List 和選取產品的數量

邏輯需求

那背後的資料邏輯呢?

A、B分別有不同的 Object而且取得資料的方式也不同

  • A 的 data 來源並非來自後端,代表說在data在本地建立不會變動
  • B 的 data 則是透過和後端 call API 取得,代表說這邊的data會變動

分析好了後,那我要怎麼樣用最少的力氣,達到最大的效益呢?

方法 - Template Method Pattern

在這裡根據 Template Method Pattern 以做出可複用的 Widget。

Design Patterns — Template Pattern from TutorialsPoint

簡單來說,做出一個架構(abstract base class),再定義自訂方法,extend 這個 abstract class 的 subclass 可以根據需求去 override 定義好的方法

UI template

第一層:卡片列表架構

UI 架構圖

創建 T 形態的 QuantitlySelection 這個 abstract class

  • Line 8: 宣告了 T 形態的 QuantitySelectionBloc
  • Line 32–33: 定義了兩個方法,getTitle() 和 getSubtitle(),分別都 return Widget
  • Line 21–22: 將宣告好的 getTtile(), getSubtitle() 方法 return 的 widget,傳到 BuyOrderQuantityLabel 裡,給每一項對應的 Label 顯示資料

以上目前為止,就是第一層卡片列表的 Template

第二層:單一項目

單一個項目
  • Line 38: 創建BuyOrderQuantityLabel 並要求將 ItemQuantityBloc、title 和 subtitle 從外面傳進來
  • Line 54: 將 title 和 subtitle 丟到 Column 裡構成 UI
  • Line 59: 用 itemQuantityBloc 裡 quantity stream 來監聽使用者在點擊增加或減少時的數量改變

休息一下喘口氣,消化一下。UI 搞定後,來看看邏輯的部分吧!

Bloc template

quantitySelectionBloc

QuantitySelectionBloc

創建 T 形態的 QuantitySelectionBloc

  • Line 8: 建立了帶有 T 形態的List 的 contructor(我們的資料會是一個List,需要丟一個 List 進來給 bloc 使用)
  • Line 9: constructor 初始化後,便把外面傳進來的 items,用 map 去 iterate items 裡面的每個一項目,讓每個項目都有自己的 itemQuantityBloc
  • Line 12-21: getSelectionQuantities() 在這邊根據需求,所以我在這邊return 了一個 Map. 簡單來說,這是一個function 用來取出每個被選購1個以上的項目
  • Line 23–26: 建立 dispose 方法進行釋放
ItemQuantityBloc

ItemQuantityBloc

itemQuantityBloc 是給單一個項目的Bloc ( 和 BuyOrderQuantityLabel 對應)

  • Line 31: 宣告 T 形態的但一個項目變數
  • Line 32: 宣告了quantity 的 stream。用來監聽數量的變化
  • Line 36: increaseQuantity function 會在新增數量的時候被 call,以增加數量
  • Line 37: 則反之,數量減少時會被 call。不過產品根據需求,下限是 0,所以同時用了max 來取得最大數量
  • Line 45: 建立 dispose 進行釋放
from GIPHY

正所謂:工欲善其事,必先利其器!

我們已經把我們的器做好了,template 建構好了!接下來,要好好發揮它!

還記得剛開始這兩個的要求嗎?這兩個需要的資料 object 不同

  • A 和 B分別是不同的 Class,兩個都 extend QuantitySelection 這個 UI template,只差在帶進去的 Object 不同
  • getTitle() 和 getSubtitle() 則是在 QuantitySelection 這個 abstract class 裡定義好的方法。因為 extend 了 QuantitySelection,A 和 B 個別根據本身的需求,implemente 個別需要的 Widget

結論

That’s it! 我們用 Template Method Pattern 達到了這次的目標!以上是在Flutter 中,在 UI 和 Bloc 上使用 Template Method Pattern 小範例給大家參考。歡迎大家指教交流一起討論!

如果這篇文章對你有用,給我拍拍手讓我知道哦:)

Reference

--

--