樣式與修飾符的設計不同。樣式不會取代修飾符,而是與修飾符並存,兩者各有不同目標。在內部,樣式就是修飾符。您可以使用修飾符執行樣式的所有功能,但樣式無法使用修飾符的所有功能。
以下是樣式與修飾符的比較:
| 功能 | 修飾符 | 樣式 |
|---|---|---|
| 主要目標 | 定義行為、語意和複雜的版面配置。修飾符會即時操控特定可組合項目的個別元素,不會從主題向下傳遞。 | 定義視覺外觀、個別項目大小和可套用主題的屬性。樣式會在主題層級運作,且可在元件層級覆寫。這些主題會向下傳遞,並套用至不同的可組合項。 |
| 邏輯 | 加法:修飾符會合併在一起,形成新的結果。 | 可覆寫 - 樣式中最後設定的屬性會勝出。樣式會做為單一屬性層,根據定義的優先順序階層互相覆寫。 |
| 主題設定 | 難以提升為主題,通常單獨使用。 | 根據設計,樣式可套用主題 (可存取 CompositionLocal),且定義一次即可在所有元件中使用。 |
| 效能 | 更新通常需要 Compose 的所有三個階段:組合、版面配置和繪製。如要讓修飾符的動畫效能良好,通常需要編寫 lambda 型版本。 | 略過組合階段,僅在版面配置和繪製階段有效,可減少重組次數。需要較少的物件配置。 |
| 動畫 | 需要使用 animate*AsState 等獨立動畫基本項目 |
內建 animate { } API,可處理部分動畫。 |
修飾符的限制
在目前的 Compose 環境中,修飾符有許多優點。不過,樣式可解決修飾符的部分限制,如下列清單所述:
- 修飾符通常是在組合階段建立。即使是顏色等微小的視覺變化,更新也可能會強制完整重新執行「組成」、「版面配置」和「繪製」,除非您建立以 Lambda 為基礎的修飾符。
- 條件修飾符需要在流暢鏈結中採用破壞性 if-else 邏輯。 如要為這些項目加上動畫效果,需要手動設定樣板狀態,且缺少高效能的「自動動畫」機制。
- 修飾符會堆疊,而非取代。您無法覆寫元件的預設邊框,只能在頂端繪製第二個邊框。
- 修飾符很難抽象化為全域主題。因此,主題通常會儲存原始值,而非可重複使用的修飾符設定。
樣式的限制
雖然樣式可以填補修飾符的部分缺口,但也有一些限制,說明樣式無法完全取代修飾符:
- 樣式是專屬的修飾符。修飾符可以執行樣式的所有操作,但反之則不然。因此,樣式可以補充修飾符,但無法取代修飾符。
- 樣式僅限於視覺化設定 (背景、邊框間距、邊框)。無法處理點擊邏輯、手勢偵測或無障礙語意等行為。
- 將樣式解析為最終狀態的成本高於套用單一修飾符。系統必須產生包含所有可能屬性值的資料結構,而繼承屬性的查閱作業會使這項作業更加複雜。
何時使用樣式而非修飾符
是否使用樣式主要取決於應用程式和用途,但下列指引有助於判斷何時應優先使用樣式而非修飾符:
- 實現主題一致性:樣式設計為「提升」至全域主題。您可以在主題中定義單一樣式,為整個應用程式建立統一的外觀,不必再將重複的修飾符傳遞至每個元件。
- 執行頻繁動畫時:樣式會在「版面配置」和「繪圖」階段評估,因此顏色或比例等屬性可以動畫呈現,同時完全略過「組合」階段。這可大幅減少效能負擔。進行視覺屬性動畫時,請使用「Style」而非修飾符。
- 覆寫與堆疊:如要取代預設屬性,請使用「樣式」。修飾符是累加的 (新增邊框會堆疊第二個邊框),而樣式則使用「最後寫入優先」邏輯,因此更容易替換背景或邊框間距,不會造成視覺混亂。
- 自訂 Material 元件:如果 Material 元件提供 Style 參數,建議您採用這種自訂方式。這些樣式可讓您存取及修改可組合項內部結構中的特定屬性,否則這些屬性可能無法存取。