我們真的需要為了宣告式UI而重寫App嗎?以Flutter與Android觀點討論

參考Flutter文件Start thinking declaratively

最近在Google的推廣之下Flutter受到愈來愈多人的注意,而Flutter的UI Layout方式,官方稱之為宣告式UI靈感來自於React

猜想其核心概念是來自於函數式程式設計。

然後根據我前一陣子使用Flutter來做Side Project的感想,宣告式UI就是在元件(Widget)之中撰寫對不同資料或狀態的顯示邏輯,所以當資料或狀態改變的時候,我們就不需要特地在去改變UI而是UI會自動更新,又或者是說與資料或狀態綁定的元件(Widget),會重新被建立,這時UI的顯示規則就會照原先已經宣告好的顯示邏輯去顯示了,這樣就是所謂的宣告式UI。

那麼這樣的做法替我們帶來了甚麼好處呢?首先UI對應資料或狀態的處理邏輯全部會被包在同一個元件(Widget)之中,未來要調整或觀看邏輯只要看元件(Widget)裏的宣告就能了解,再來也不會有命令式程式設計那樣改變UI的語法散落各地,在追蹤程式碼時還需要了解脈絡或是順序。

所以聽起來真得很棒?我們應該趕快擁抱宣告式UI?雖然Android跟iOS都大力的擁抱了宣告式UI(Android => Jetpack Compose. iOS => SwiftUI)但是其實宣告式UI並沒真的好到要特地重寫的地步,其實React最早也說過自己要解決的問題是狀態龐大且複雜的UI問題,但大部分的App在現代框架架構分明的狀況下,要搞到架構龐大且複雜到不可維護的狀況,我自己是覺得蠻困難的啦。

而在Android要依照資料或狀態頻繁更新的場景,也有Adapter這個模式扛起了類似宣告式UI的責任,而命令式通常也是用在更新比較沒那麼頻繁的部分,在加上現代強大的IDE要找到相對應的程式碼也沒有這麼困難。

另外如果在Android有客製過View其實就知道,View本身就像是StatefulWidget是會保留著狀態,在資料更新時透過命令再去更新,其實跟Flutter要另外下setState()有點類似,但時間點不同,結果Flutter也是要為了這個setState()付出代價,需要各種狀態管理來達成更好的狀態維護與更新效率,當然大部分的App不會遇到就是,但也是會被潮流推著去使用,這邊也感覺的出為了解決一個問題,卻要解決更多衍生出來的問題,但終究我不是為了這些選上Flutter就是了,我是看上跨平台架構的解決方案。

Flutter這種宣告式UI也間接地完成了另一個每個前端在提倡且想達成的目的資料綁定(data binding),又或者是資料綁定才是主要目的?但在Android跟iOS也有MVVM架構可以達成,但其實也沒聽過多少人為了資料綁定而換架構的?但Angular中的各種單向綁定跟雙向綁定真的就是省心好用,在Flutter中其實也有著Provider能做到Angular中的注入再配合Flutter本身的特性做更新。

而命令式改變UI的語法散落各地的問題,在宣告式中其實就轉變成了資料或狀態的更新散落各地的問題,我自己是覺得換湯不換藥,只是換了個模式問題依舊還在,我也常在思考如果Android跟iOS都在大力擁抱宣告式UI的話那我為何不寫Flutter就好呢?到時是不是在App又會掀起狀態管理大戰呢?

另外一個思考層面就是,如果採用了這樣的UI架構設計之後,Android跟iOS能做到更強大的hot reload,那麼我可能才會有更多的動力去擁抱Jetpack Compose,因為現在Android本身也有堪用的hot reload,不然其實會採取跟現在對Kotlin一樣的策略,全新功能才會採用新的東西去寫,一方面體會、一方面學習,特地為了這些東西重寫投資報酬率太低了,如果沒有什麼行銷導向的目的,不划算。

最後你是怎麼看待宣告式UI或是Jetpack Compose與SwiftUI的呢?歡迎跟我們分享

留言