Daily Digest

每日新聞摘要

2026年02月27日

今日總結

內容會跟隨語言切換。

📝 今日焦點 • 以串流為主的 DataHandler 實作(以 InputStream 為來源)可避免將大型檔案一次載入記憶體,降低 OOM 風險並維持效能與可測試性;同時注意 javax.activation 自 Java11 起需額外引入相依。 • Kotlin 生態與工具升級帶來雙面效應:Kotlin 2.0 導致 React Native Track Player 在 Expo SDK 51/52 與新架構中出現 build-time null-safety 崩潰,需釐清相依與相容性並採行修補或回退;而 Kotlin 2.2、Compose 與 AI 工具則能顯著縮短從概念到可用 MVP 的開發時間。 • 協程原語(Channel/SharedFlow/StateFlow)選擇直接影響事件 vs 狀態的交付語意,錯誤選型會導致遺失更新或重複處理,對 UI 一致性與測試有實際影響。 🔧 效能最佳化 • 對大型二進位資料,改用 getBinaryStream() + 自訂 DataSource 建立 DataHandler,讓上層以串流處理而非一次性 byte[],直接降低記憶體峰值與 GC 壓力。 • Compose 相關:將 Canvas 匯出為 Bitmap 時要處理裝置密度、縮放與記憶體使用,並以背景執行緒與適當壓縮避免 UI 卡頓;同時注意不可變列表被視為「不穩定」會引發多餘重組,透過穩定表示或減少重建可提升 UI 效能。 • 編譯時間問題常來自隱性錯誤設定而非單一版本升級;逐步診斷、優化 build script 與修正錯誤配置,比盲目怪罪工具版本更能恢復生產力。 🏗 架構設計 • 將驗證結果建模為帶有上下文欄位的 sealed 資料型別,能讓 UI 保持「愚笨」,直接依錯誤描述渲染訊息,促進關注點分離與驗證邏輯重用。 • Jetpack Compose:完整動畫化的滑動操作卡片示範如何結合手勢、動畫原語與錨點物理行為,以達成自然的停止、顏色過渡與撤銷支援,適合用於生產級互動元件。 • 資料結構與可維護性:AxTuple 提供以複合鍵扁平化多維 HashMap 的實作,改善可讀性與查詢效能;若鍵需要領域行為仍建議建立專門類別。 • 在微服務架構評估時,以「獨立部署能力、邊界清晰與團隊擁有權」等屬性替代簡單貼標籤,避免分散式單體的反模式。 ✅ 測試與品質 • 貨幣驗證:若需求要嚴格格式檢查,使用正則表達式可精確控制並在單元測試中驗證邊界;若需地區化與容錯解析,NumberFormat 提供更簡便但較寬鬆的行為,選擇應依驗證嚴格度而定。 • 大型相依升級(如 Room 2.6.1→2.7.1)與生產問題處理需以系統性除錯、回溯測試與安全發布策略為主,並透過增加監控與測試避免回歸。 • 資深工程師在生產事件中偏向根因分析、可重現驗證與可控回滾或自動化修復,事後補強測試與觀測性以防復發,這套流程是提升生產穩定性的關鍵。 🚀 語言演進 • 將 Java 類別轉寫為 Kotlin 可顯著簡化樣板:利用主構造子、private val/var 與型別推斷在保留行為下縮短程式碼,提升可讀性與開發速度。 • Java 的型別限制(介面、抽象類別、enum、以及 Java 17+ 的 sealed)會直接影響可實例化方式:理解這些語意可避免編譯錯誤並設計正確的替代實作。 • 工具與語言演進讓快速原型轉為可維護 MVP 成為可行路徑,但升級(如 Kotlin 2.0→2.2)仍需關注相依相容性與逐步驗證以免破壞現有整合。

01

Convert an InputStream to a DataHandler in Java

Baeldung 作者:Sidrah Abdullah 發布:02-27 12:37

在 Java 中將 InputStream 轉換為 DataHandler

將 InputStream 包裝在自訂 DataSource 中並傳給 DataHandler,可串流處理大型檔案而不需一次載入全部記憶體。

重點摘要

避免使用 getBytes() 讀取整個檔案以免耗盡記憶體
使用 getBinaryStream() 並以自訂 DataSource 提供 InputStream
可於 DataSource 中指定 MIME 類型以確保正確的內容型別

本文說明如何在 Java 中將 InputStream 轉為 DataHandler 並維持記憶體效率。直接以 byte[](如 ResultSet.getBytes())讀取會把整個檔案載入記憶體,處理大型檔案時可能導致 OutOfMemoryError。替代作法是透過 getBinaryStream() 取得 InputStream,實作一個自訂的 DataSource(實作 getInputStream、getOutputStream 可拋出 UnsupportedOperationException、getContentType、getName),然後以該 DataSource 建立 DataHandler,讓資料能以串流方式讀取而非一次性載入。文章還提醒 javax.activation 自 Java 11 起不再內建,需額外加入依賴,並示範如何擴充建構子以接受 MIME 類型以便精確指定內容型別。

02

Matching Currency Symbols in Java

Baeldung 作者:Yadier Betancourt 發布:02-27 12:40

在 Java 中匹配貨幣符號

可以用正則表達式做嚴格驗證,或用 NumberFormat 做具地區設定的解析。

重點摘要

正則表達式可做嚴格且精確的格式驗證
NumberFormat 支援地區化解析但容錯寬鬆
範例涵蓋美金小數與千位分隔的 pattern 與單元測試

本文由 Yadier Betancourt 說明在 Java 中匹配與驗證貨幣符號的兩種方法:正則表達式與 NumberFormat。正則表達式可精準且嚴格地驗證格式,示範美金金額的 pattern(含小數與千位分隔)並以單元測試檢查各種有效與無效輸入;NumberFormat.getCurrencyInstance(Locale.US) 提供簡單且具地區化的解析,會自動處理符號與分組,但較寬鬆,會接受像 "$12asdf" 的部分有效字串。文章比較兩者在嚴格性、地區支援與複雜度的差異,並建議依驗證需求選擇適合方法,範例程式碼放在 GitHub。

03

Resolving the “Cannot instantiate the type” Compilation Error

Baeldung 作者:baeldung 發布:02-27 12:45

解決「Cannot instantiate the type」編譯錯誤

當程式嘗試用 new 建立 Java 不允許直接實例化的型別時,編譯器會報錯「Cannot instantiate the type」。

重點摘要

介面、抽象類別與列舉無法以 new 直接實例化
介面需改用具體實作類別,抽象類別需使用具體子類別
Java 17+ 的 sealed 類別限制可被繼承/實作的子型別,但仍不可直接實例化

此錯誤表示程式試圖實例化 Java 設計上不允許直接建立的型別。介面只定義契約、無完整實作;抽象類別含抽象方法、需由子類填補實作;列舉的實例在載入時由 JVM 生成,建構子隱含為 private。解法依型別而異:對介面使用具體實作(例如用 ArrayList 建立 List)、對抽象類別使用完整實作的子類別、對列舉直接引用既有常數。Java 17 起的 sealed 類型則明確限制允許的實作或繼承類別集合,但仍必須透過允許的實作來建立物件。

04

From Java to Kotlin: How Would You Rewrite This Class?

Dev.to Kotlin 作者:Felipe Cezar 發布:02-27 13:14

從 Java 到 Kotlin:如何重寫這個類別?

使用 Kotlin 的主構造子與 val/var 在保留行為不變的前提下,省去 Java 的大量樣板程式碼。

重點摘要

Kotlin 預設為 public,不需明確提供 public 關鍵字。
在類別表頭以 val/var 宣告的參數會同時建立並賦值欄位。
可變欄位用 var 並在類別本體設定預設值,型別由 Kotlin 推斷。

本文以一個簡單的 Java 類別為例說明如何忠實轉寫為 Kotlin:原始類別包含兩個由建構子賦值的私有欄位(codigo、nome)與兩個帶預設值的私有欄位(numero=0、texto="EscolaX")。Kotlin 可在類別表頭使用主構造子,並透過在參數前加上 private val 將參數同時宣告為不可變欄位,省去 this.x = x 的賦值程式碼;帶預設值且可變的欄位則以 private var 放在類別本體,且型別由編譯器推斷。最終結果是行為相同但程式碼更簡潔,突顯 Kotlin 減少 Java 樣板且更具表達力的設計。

05

UI shouldn't think about validation

Dev.to Kotlin 作者:Vadym Yaroshchuk 發布:02-27 14:14

UI 不該負責思考驗證

呈現層應提供具資料的驗證上下文,讓 UI 自行呈現錯誤而不需計算領域細節。

重點摘要

讓 UI 保持「愚笨」,不要讓它決定或計算如何顯示驗證錯誤。
用 enum 表示問題會迫使 UI 去計算或查域限制;使用帶資料的 sealed 型別可解決此問題。
資料豐富的錯誤物件可強化關注點分離,並支援驗證器在畫面間的組合與重用。

作者描述將驗證邏輯與呈現層界定清楚,以便 UI 保持愚笨:直接傳遞顯示字串或 enum 會把呈現細節或領域限制洩漏到 UI,使 UI 還得計算(例如最大長度)才能顯示有意義的錯誤訊息。作者改用 Kotlin 的 sealed 型別與具資料的錯誤物件,讓驗證器回傳包含上下文欄位(如 min/max 長度與當前長度)的問題描述。如此 UI 可直接依據這些詳細資訊渲染錯誤,不需了解領域不變條件,消除了 UI 的「決策上下文搜尋」,同時維持關注點分離並便於驗證器組合與跨畫面重用;作者認為少量重複是合理的交換。

06

How I Built a Bank-Grade Emulator Detector to Stop Hackers Dead — Part 1

Medium Kotlin 作者:Harrison Kuria 發布:02-27 08:49

我如何打造銀行級模擬器偵測器以擋住駭客 — 第 1 部分

我所接觸過的銀行應用程式與駭客之間的無聲戰爭。

重點摘要

揭示駭客與銀行應用間長期且不顯眼的攻防
說明建置銀行級模擬器偵測器的動機
第一篇概述問題、攻擊模型與設計目標

本文第一部分以作者在多個銀行應用上的實務經驗為基礎,描述了與駭客之間那場常被忽略的「無聲戰爭」,並說明為何需要專門的模擬器偵測機制。作者未在此處提供完整實作細節,而是先釐清問題範圍、可能的攻擊模型與實務上的設計目標與限制,說明在真實環境中降低誤報與兼顧部署可行性的重要性。本系列將以多篇文章逐步揭露偵測方法、架構取捨與測試經驗,強調可在生產環境中實際防禦自動化與模擬器驅動的攻擊。

07

Fixing the Kotlin 2.0 Crash in React Native Track Player (Expo SDK 51/52)

Medium Kotlin 作者:M Irfan 發布:02-27 11:17

修復 React Native Track Player 在 Kotlin 2.0 的崩潰(Expo SDK 51/52)

一篇針對 React Native 0.75+ 與新架構中 compileDebugKotlin null-safety 錯誤的完整修復指南。

重點摘要

針對 Kotlin 2.0 導致的 Track Player 崩潰
重點說明 compileDebugKotlin 的 null-safety 錯誤
適用於 Expo SDK 51/52 與 React Native 新架構

本文為針對 Expo SDK 51/52 與 React Native 新架構中,Kotlin 2.0 導致的 React Native Track Player 崩潰所撰寫的完整指南。重點說明 React Native 0.75+ 編譯時出現的 compileDebugKotlin null-safety 錯誤,解析此錯誤與 Kotlin 2.0、Track Player 相依性及版本相容性的關係,並提出診斷方向與可行的調整與替代方案。文章旨在協助升級後遇到建置失敗的開發者,提供根因說明與實務可行的修復建議,特別針對 Expo SDK 51/52 與新架構應用場景。

08

Building a Fully Animated Swipe-to-Action Card in Jetpack Compose: A Deep Dive

Medium Kotlin 作者:Ramadan Sayed 發布:02-27 11:19

在 Jetpack Compose 中構建完全動畫化的滑動操作卡片:深入解析

本文呈現在 Jetpack Compose 中完整實現一個雙向揭露的滑動操作卡片,包含動畫化的操作圖示、基於進度的顏色過渡、錨點彈性吸附物理行為與撤銷支援。

重點摘要

雙向揭露與動畫化的操作圖示
根據滑動進度的顏色漸變
錨點吸附物理與撤銷機制

本文深入說明如何在 Jetpack Compose 中構建一個完全動畫化的滑動操作卡片。文章涵蓋雙向揭露設計,當用戶滑動時會顯示並動畫化操作圖示;說明如何依據滑動距離驅動顏色過渡,讓界面回饋更細緻;並介紹使用錨點吸附的物理行為來達成自然且可預期的停止位置,以及提供撤銷支援以回復誤觸操作。整體重點放在結合 Compose 的手勢處理、動畫原語與狀態管理,達成可用於真實應用的流暢互動元件。

09

Jetpack Compose Canvas to Bitmap: A Complete Guide

Medium Kotlin 作者:Chirag T 發布:02-27 11:20

Jetpack Compose Canvas 轉 Bitmap:完整指南

你是否曾在 Jetpack Compose 的 Canvas 上畫出漂亮的圖,然後想「要是能把它儲存成圖片就好了」?

重點摘要

將 Compose Canvas 的繪圖匯出為 Bitmap
處理解析度、縮放與記憶體優化
儲存與分享流程與常見陷阱(權限、格式)

本文說明如何將 Jetpack Compose 的 Canvas 畫面保存為影像檔,從概念到實作步驟皆有覆蓋。文章解釋為何需要匯出 bitmap,並比較可行方法(如使用 Compose 的匯出 API 或在 Android 的 Bitmap 上繪製),示範如何擷取 bitmap、處理裝置密度與縮放、寫入儲存空間與分享檔案。內容也說明公開與應用程式專屬儲存的差異、執行緒與效能建議,以及權限與檔案格式等常見問題的處理方式;搭配範例程式與除錯提示,協助開發者建立穩健的匯出流程。

10

Channel vs SharedFlow vs StateFlow: 3 Tools, 3 Jobs: Pick Wrong and Your App Breaks

Medium Kotlin 作者:Ramadan Sayed 發布:02-27 11:26

Channel vs SharedFlow vs StateFlow:三把工具、三種任務——選錯會讓你的應用出問題

了解何時使用 Channel、SharedFlow 或 StateFlow、它們如何傳遞資料,以及選錯原語會如何破壞應用行為。

重點摘要

Channel:適合一次性事件或點對點的生產者-消費者通訊。
SharedFlow:熱式多播,能透過 replay 與緩衝設定廣播事件給多個訂閱者。
StateFlow:狀態持有者,始終保留並發出最新值,適合 UI 同步。

本文比較 Kotlin 協程的三種常用原語:Channel、SharedFlow 與 StateFlow,說明各自的使用時機與資料傳遞語意,協助避免常見錯誤。Channel 適合一次性或點對點的訊息交換,SharedFlow 是可設定 replay 與緩衝的熱流,用於向多個訂閱者廣播事件,而 StateFlow 作為狀態持有者,會保留並立即提供最新值給觀察者,適合 UI 狀態同步。作者指出在緩衝、重放與訂閱者行為上的差異,並示範若將事件與狀態混用,可能導致遺漏更新、重複處理或 UI 不一致,最後以 Android 相關範例做比較,方便選擇合適工具。

11

Stop Calling It Microservices — You Probably Built a Distributed Monolith

Medium Kotlin 作者:Tomas Balaz 發布:02-27 12:36

別再稱它為微服務——你很可能建成了分散式單體

作者以14年後端開發經驗指出,許多自稱「微服務」的系統其實表現得像分散式單體。

重點摘要

自稱微服務的系統常是分散式單體
關鍵在於能否獨立部署、耦合程度與職責劃分
經驗會揭露常見的架構與運維反模式

Tomas Balaz 以14年的後端實務經驗提醒讀者,不應僅以「微服務」標籤定義系統。很多團隊把系統拆成多個服務,卻因部署、資料或行為上的緊密耦合,實際上仍是分散式單體。稱謂掩蓋了真正的問題;應以能否獨立部署、清晰的邊界和團隊擁有權等具體屬性評估架構。文章指出經驗會暴露出一系列重複出現的反模式,建議把重點放在提升自治性與可操作性,而不是把採用「微服務」當成最終目標。

12

How Senior Android Engineers Debug Production Issues Differently

Medium Kotlin 作者:YADNYESH RANA 發布:02-27 13:01

資深 Android 工程師如何以不同方式除錯生產問題

資深 Android 工程師在調查生產問題時重視根因分析、可觀測性與安全且可重複的修復流程。

重點摘要

以根因分析為優先,不只做權宜修補
善用日誌、追蹤與指標等可觀測性工具定位問題
透過自動化檢測、漸進回滾與跨團隊協作來解決事件

本文探討資深 Android 工程師在處理生產問題時的不同做法。與偏向立即修補的做法不同,資深工程師會以結構化的分級與重現流程找出根本原因,並利用日誌、分散式追蹤與監控指標進行定位。他們在衡量用戶影響與工程成本後,選擇安全的漸進部署或自動化修復,必要時會加入診斷性程式碼以利調查。事後會紀錄教訓、強化測試與監控來預防復發,並與後端、QA 與產品團隊協同處理,以達成更穩定的生產環境。

13

Room 2.6.1 to 2.7.1 in a Large Codebase: Challenges and Lessons Learned

Medium Kotlin 作者:Piotr Żołnacz 發布:02-27 13:31

Room 2.6.1 到 2.7.1 在大型程式碼庫中的挑戰與經驗教訓

深入除錯、根本原因分析與安全發布。

重點摘要

深入除錯
根本原因分析
安全發布

本文回顧在大型程式碼庫中將 Room 從 2.6.1 升級到 2.7.1 的過程與所得經驗,重點描述升級過程中遇到的實務挑戰。作者著重於進行深入除錯、系統性找出問題根本原因,並採取可行的安全發布策略以避免對生產環境造成影響。文章偏向實作與調查流程的分享,說明如何在既有專案中衡量風險與進度、驗證變更與採取緩解措施,並提供供團隊在執行相似相依升級時的實務建議和檢核重點。

14

Why Your Android Build Times Still Hurt in 2026 And What to Actually Do About It

Medium Kotlin 作者:AndroidLab by Andre 發布:02-27 13:59

為何你的 Android 編譯時間在 2026 年仍然痛苦,以及真正可行的解法

Kotlin 2.2 與 Gradle 9 不是全部問題——隱藏的設定錯誤每天都在默默地吞噬你的生產力。

重點摘要

Kotlin 2.2 與 Gradle 9 會影響編譯效能
隱藏的設定錯誤會造成重大慢化
需要具體診斷與修正才能恢復開發效率

本文探討為何在 2026 年 Android 專案的編譯時間仍然很長,指出 Kotlin 2.2 與 Gradle 9 等新版工具只是部分因素。更常見且危險的是專案中的隱性設定錯誤:那些開發者不常檢視的設定會逐步累積並顯著增加編譯開銷,侵蝕日常生產力。文章主張不要僅將責任推給版本,而是要針對實際瓶頸進行診斷並採取具體措施,例如找出錯誤設定、優化建置腳本與調整工具設定,以達到減少編譯時間與恢復開發流程的目的。

15

Killing Off “Quick Android Apps” in a World of Modern Tooling

Medium Kotlin 作者:AndroidLab by Andre 發布:02-27 14:00

在現代化工具下淘汰「快速 Android 應用」

我們採用 Kotlin 2.2、Jetpack Compose 與 AI 驅動工具,走向以 2 小時 MVP 為核心,取代傳統的快速應用作法。

重點摘要

以 2 小時 MVP 為開發節奏
Kotlin 2.2 與 Compose 簡化 UI 與開發流程
AI 工具加速重複性工作與原型建立

本文指出,藉由 Kotlin 2.2、Jetpack Compose 與 AI 驅動的開發工具,可以在數小時內完成具意義的最小可行產品(MVP),因此傳統所謂的「快速 Android 應用」逐漸沒落。作者描述一種相反方向:不再倚賴臨時與難以維護的快速構建,而是運用現代語言特性、宣告式 UI 與自動化輔助來迅速且穩健地建立原型。這樣的做法不僅提高建構速度,也使產出在可維護性和一致性上更具優勢,反映出 Android 生態系統工具進步後的開發新常態。

16

JSON to Kotlin Data Class: Complete Guide with kotlinx.serialization, Gson and Moshi

Dev.to Kotlin 作者:arenasbob2024-cell 發布:02-27 01:07

JSON 轉 Kotlin 資料類別:使用 kotlinx.serialization、Gson 與 Moshi 的完整指南

示範如何將 JSON 轉為適用於 Android 與多平台的 Kotlin 資料類別。

重點摘要

示範 kotlinx.serialization 的 @Serializable 與 @SerialName 用法
提供 Gson 與 Moshi 的替代實作與適配器範例
涵蓋巢狀清單、nullable/預設值、sealed class、Ktor 與 Retrofit 整合

本文示範如何將 JSON 轉為 Kotlin 資料類別,適用於 Android 與多平台,並示範 kotlinx.serialization、Gson 與 Moshi 的實作。內容包含註解範例(@Serializable、@SerialName、@JsonClass/@Json)、序列化/反序列化、巢狀物件與清單處理、nullable 與預設值、以及 sealed class 表示聯合類型(含型別判別器)。並示範 Ktor 客戶端的協程取用與 Retrofit(GsonConverterFactory)整合,另推薦 DevToolBox 的 JSON-to-Kotlin 快速產生器。

17

Replacing Nested Maps with Tuple Keys in Java and Kotlin

Dev.to Kotlin 作者:Robin Alex Panicker 發布:02-27 05:07

在 Java 與 Kotlin 中以 Tuple 鍵取代巢狀 Map

AxTuple 將多層 Map 攤平為不可變且 hash-safe 的複合鍵,簡化程式碼並避免巢狀 Map 的複雜性。

重點摘要

以 Map<Tuple, V> 取代 Map<A, Map<B, Map<C, V>>>
AxTuple 提供正確的 equals()/hashCode() 與不可變性
NamedTuple 可用鍵名提升可讀性與除錯便利性

文章介紹 AxTuple(ax-tuple-java)如何在 Java 與 Kotlin 中把深層巢狀 HashMap 攤平成單層 Map,以 Tuple 作為複合鍵來簡化設計與使用。範例展示用 Tuple.of("prod","us-east","dark_mode") 作為單一鍵,搭配 Map.merge 做計數器;AxTuple 保證 equals()、hashCode() 與不可變性,因此即便在不同方法重建鍵也能正確對應。文中也示範 NamedTuple 作為命名鍵的替代方案以提升除錯與可讀性,並報告在約 10 萬筆插入與查詢測試中,扁平化 Map 在可讀性、維護性、重構安全性與迴圈性能上都有明顯提升。建議在多維度計數或分析場景採用,若鍵需豐富領域行為則另建類別。

18

Identifying the “4 JDKs” in Android Studio

Medium Kotlin 作者:chanzmao 發布:02-27 00:18

辨識 Android Studio 中的「4 個 JDK」

在 Android Studio 各處使用的 JDK 存在令人挫折的不一致情形。

重點摘要

討論與 Android Studio 相關的四種 JDK
指出 JDK 選擇或使用上的令人挫折的不一致
作者 chanzmao 的原文刊載於 Medium

本摘要基於可得資訊有限:僅有標題「辨識 Android Studio 中的『4 個 JDK』」及短句「令人挫折的不一致」。作者 chanzmao 似乎針對在使用 Android Studio 時可能涉及的四種不同 JDK 來源進行辨識,並指出各處所使用 JDK 的不一致性帶來的困擾。由於未提供完整內文,本段僅重述標題與摘句所暗示的範圍與目的,未包含具體步驟、診斷或解決建議。如需詳細說明、範例或修正建議,請參閱作者在 Medium 的原文連結。

19

The Great Kotlin List Paradox: Why Jetpack Compose Thinks Your Immutable Lists Are Unstable

Medium Kotlin 作者:Abdulkadir Ali 發布:02-27 02:11

Kotlin 列表的大悖論:為何 Jetpack Compose 認定你的不可變列表不穩定

在以 MVVM 與 Jetpack Compose 建構的應用中,即便是不可變的 Kotlin 列表,Compose 也可能視為不穩定,導致意外的重組與效能問題。

重點摘要

Jetpack Compose 可能把不可變的 Kotlin 列表標示為不穩定。
此行為會引發不必要的重組,影響 UI 效能。
文章解析成因並提供避免多餘重組的實務建議。

本文探討一個在 Jetpack Compose 中常見但令人困惑的現象:即便開發者使用不可變的 Kotlin 列表,Compose 仍可能將其視為「不穩定」,進而觸發額外的重組,影響介面效能。作者說明了 Compose 判定資料型別穩定性的方式、為何特定的列表表現會不通過這些判斷,以及這對 MVVM 架構下 UI 呈現的實際影響。文章不僅分析問題成因,也提出實務上可採取的做法,例如避免在狀態更新時不必要地重建列表、採用能讓 Compose 視為穩定的表示方式等,以維持不可變資料設計同時避免過度重組。