一個 for 迴圈被還原了:Jetpack Compose 的介面設計觀察
從 LazyColumn 與 AnimatedVisibility 這兩段程式碼看起,觀察 Jetpack Compose 如何把 Android 開發者的心智模型從「怎麼做」重新設計成「是什麼」。
2026 年 9 月 3 日,掘金上一篇名為「我為什麼喜歡 Compose?」的文章重新把這套 Android 宣告式 UI 框架拉回討論區。文章的時間感值得先交代:Compose 1.0 的第一個穩定版發布於 2021 年 7 月,到今年 8 月已迭代至 1.12。五年過去,這不是一則新聞,而是一份使用者的回顧,而回顧往往比發表會誠實。
先從最小的細節看起:一段 LazyColumn 的程式碼。在舊的 View 體系裡,顯示一個列表至少要準備四份東西,XML 的 item 佈局、ViewHolder、Adapter,以及 DiffUtil.Callback。這四份東西各自獨立,彼此靠約定連接,於是開發者的工作變成反覆核對:某個條件分支裡忘了重置狀態,列表複用時就會顯示錯誤的畫面;比較邏輯寫漏一條,列表就會閃動。換句話說,舊體系把「顯示一個列表」這件事拆成了四個檔案之間的手工同步。
Compose 做的設計決策,是把這四份東西收攏回一行.items(listOfItems, key = { it.id })。列表回到它本來的樣貌:一個 for 迴圈。key 負責標識每一項的身分,重組時 Compose 用它追蹤 item,列表重新排序後,狀態會留在正確的那一行上。這裡的取捨很清楚:框架喫掉模板碼,換取開發者只描述「列表是什麼」,而不再指揮「列表怎麼被建造」。
從「怎麼做」到「是什麼」,是一次心智模型的重新排版
宣告式 UI 並非 Compose 首創,React 早走了好幾年。但原文作者點出一個更貼身的觀察:它重塑了 Android 開發者的心智模型。過去的問題是「怎麼做」,現在的問題變成「是什麼」。
這句話用設計的語言翻譯,就是互動介面的層級被重新排過了。舊 View 體系裡,開發者面對的是命令式的控制面板:先設 alpha 為零,再設為可見,最後播放淡入動畫;隱藏時要先播動畫,再在結束回調裡設成 GONE。順序錯一步,動畫就會被截斷。這套流程強迫使用者(這裡的使用者是開發者)記住狀態機的每個轉場。而 Compose 的 AnimatedVisibility 只需要一個布林值,退出動畫還沒播完之前,內容會繼續留在組合樹裡,框架替你等它演完。
同樣把老介面拆掉重組的例子,可以對照我們先前寫過的Audacity 4.0 的介面重構觀察:一套用了二十多年的按鈕與選單被換掉時,真正的工程在於使用者肌肉記憶的遷移。Compose 面對的也是同一種遷移,只是它的使用者是每天寫 XML 的開發者。
動畫體系的收編,是把選擇題收掉
舊 Android 的動畫是個博物館:AnimationUtils 的補間動畫放在 XML 裡、ObjectAnimator 與 ValueAnimator 的屬性動畫、LayoutTransition 與 animateLayoutChanges、TransitionManager 的場景過渡,RecyclerView 還自帶一套 ItemAnimator。它們的 API 風格各不相同,能力邊界又互相重疊。原文的形容很實在:很多時候你並不清楚眼前的場景該選哪一個。
這是典型的介面噪音。當一個工具箱裡有六把功能相近的扳手,使用者的第一個決策成本就花在選扳手上。Compose 的做法是收編:fadeIn()、expandVertically() 這類修飾詞可以相加組合,進出場邏輯寫在同一個 AnimatedVisibility 裡,宣告式的本質讓「動畫中的畫面」也只是一種狀態,而狀態正是這套框架唯一的第一公民。
與其說這是功能升級,不如說是資訊架構的重整。就像一個好的排版設計會把同層級的訊息收進同一種視覺語言,Compose 把散落在五套體系裡的動畫能力,收進同一套可組合的語法。開發者讀程式碼的方式,從逐行追蹤執行順序,變成一眼看出畫面結構。
模板碼的消失,是一種誠實
回到最初的比較。RecyclerView 加 DiffUtil 並非做不出流暢的列表,熟悉那套體系的人至今仍能寫得又快又穩。問題在於那份熟練的內容:大部分是模板碼與防錯檢查,是「讓四份檔案保持同步」的勞務。Compose 把這些勞務移交給框架之後,開發者留下的工作才是設計本身,決定一行的視覺、一個過場的節奏、一個 key 的語意。
當然,宣告式也有它的代價:重組的效能陷阱、狀態提升的思考負擔,這些在原文的回顧視角裡被略過了。但五年下來,方向是對的。好的介面設計從來都是讓反覆出現的判斷被系統吸收,讓人只留下需要人來判斷的部分。Compose 對 Android 開發者做的,正是這件事。
主題