---
# System prepended metadata

title: '[Video Note] [Android] [Jetpack Compose] Philipp Lackner - The BEST Way to Implement a Search In Jetpack Compose'
tags: [Jetpack Compose, Android, Video Note]

---

### 影片開場與功能介紹

* 展示如何在 Android 中實作一個彈性高、可自訂的搜尋功能。
* 搜尋功能包含文字延遲輸入（500 毫秒）後才觸發查詢，適合搭配網路請求。
* 支援多種搜尋規則，如：姓名全名、帶空格、縮寫等。
* 實作會用到 Kotlin Flow 操作符（如 `combine`, `debounce` 等）。

---

### 建立 ViewModel 與狀態管理

* 使用 `ViewModel` 管理搜尋邏輯與 UI 狀態。
* 建立 `MutableStateFlow` 用於搜尋文字、是否正在搜尋、以及人員清單。
* 對外只暴露不可變版本 (`StateFlow`) 供 UI 使用。

---

### 定義 Person 資料模型與搜尋邏輯

* 宣告 `Person` 資料類別，包含 `firstName` 和 `lastName`。
* 在 `Person` 類別中定義 `doesMatchSearchQuery` 方法
* 產生姓名的不同組合（全名不加空格、有空格、縮寫）。
* 支援模糊搜尋與不區分大小寫。
* 使用 `any { it.contains(query, ignoreCase = true) }` 判斷是否符合。

---

### 處理搜尋輸入與文字變更

* 建立 `onSearchTextChange` 方法，更新 `searchText` 的值。
* 輸入變更會觸發後續搜尋邏輯。

---

### 建立搜尋邏輯與 Flow 操作符應用

* 使用 `combine` 操作符結合 `searchText` 與人員清單的 `StateFlow`。
* 當搜尋文字或資料來源變更時自動更新結果。
* 若搜尋文字為空白，回傳所有人員；否則套用 `.filter` 搭配 `doesMatchSearchQuery`。
* 使用 `stateIn` 將 Flow 轉為可持續狀態的 `StateFlow`，設定作用域與初始值。

---

### 延伸設計與最佳實踐建議

* 若搜尋邏輯複雜可考慮建立 `Searchable` 介面以支援多種資料類型。
* 搜尋邏輯執行於本地且輕量時，建議使用此種實作方式。
* 此方法適合簡潔、高效的即時搜尋需求。

---

### 建立 UI 畫面與基本搜尋輸入

* 在 `MainActivity` 使用 `Column` 排列搜尋欄與結果清單。
* 使用 `TextField` 顯示搜尋欄，值來源為 `viewModel.searchText.collectAsState()`。
* `onValueChange` 呼叫 `viewModel.onSearchTextChange()` 更新搜尋文字。
* 下方使用 `LazyColumn` 顯示搜尋結果，來自 `viewModel.persons.collectAsState()`。
* 每個人員顯示名字與姓氏，加入基本樣式（如 padding、填滿寬度）。

---

### 延遲搜尋邏輯與 debounce 應用

* 對搜尋文字加上 `.debounce(1000)`（或自訂時間）以延遲觸發搜尋邏輯。
* 當輸入變更後經過指定時間未再次輸入才會執行搜尋，避免每次輸入都呼叫 API 或資料庫查詢。
* 在 ViewModel 使用 `.onEach {}` 搭配 `isSearching.update { true/false }` 管理搜尋進行中狀態。

---

### 顯示搜尋中動畫

* 根據 `isSearching` 狀態控制是否顯示搜尋結果或載入動畫。
* 搜尋中時顯示 `CircularProgressIndicator`，置中顯示。
* 搜尋結束時顯示 `LazyColumn` 結果清單。

---

### 模擬網路延遲與測試動畫

* 在 ViewModel 加入人工延遲（如 `delay(2000)`）模擬網路查詢耗時。
* 執行搜尋後會先顯示載入動畫，待延遲結束後顯示搜尋結果。
* 真實情境中此延遲將由 API 查詢替代。

---

### 最佳實踐與總結建議

* 使用 Flow 的 debounce 與 combine 操作符可簡潔實作彈性搜尋。
* 使用狀態管理顯示進度條提升使用者體驗。
* 搜尋邏輯集中於 ViewModel，維持 UI 與邏輯分離。
* 適合本地與網路型搜尋實作，可擴展至商業專案中使用。




# Terminology
* **ViewModel**：Android 架構元件，用於封裝 UI 邏輯並管理狀態，與 UI 元件分離。
* **StateFlow**：一種可觀察且具備狀態的 Kotlin Flow，適用於 UI 狀態管理。
* **MutableStateFlow**：StateFlow 的可變版本，用於更新狀態。
* **asStateFlow()**：將 MutableStateFlow 暴露為唯讀版本，避免 UI 修改狀態。
* **Search Query**：使用者輸入的搜尋文字，用於篩選資料。
* **Progress Bar**：顯示加載中狀態的 UI 元件。
* **Person 資料類別**：定義資料模型，包含 firstName 和 lastName。
* **doesMatchSearchQuery()**：用於檢查 Person 是否符合搜尋條件的函數。
* **Custom Search Rule**：自定義的搜尋邏輯，例如使用姓名縮寫進行比對。
* **Kotlin Flow**：一種非同步資料流工具，可連接操作符並構建反應式邏輯。
* **combine 操作符**：將多個 flow 組合並轉換成新 flow 的操作符。
* **filter 操作符**：根據條件篩選集合元素的 flow 操作符。
* **map 操作符**：將一個 flow 中的資料轉換成另一種形式。
* **stateIn 操作符**：將 Flow 轉為 StateFlow 並附帶初始值與共享策略。
* **SharingStarted.WhileSubscribed()**：Flow 的共享策略，僅當有訂閱者時才執行。
* **viewModelScope**：ViewModel 中的協程範圍，用於啟動非同步操作。
* **Initial Value**：StateFlow 初始值，當 Flow 尚未發出資料時的預設值。
* **Debounce**：延遲發送資料的 flow 操作符，避免頻繁觸發。
* **Delay**：延遲某段操作或資料流的發送。
* **UI Mapping Logic**：將資料轉換為 UI 狀態的邏輯層。
* **searchText**：搜尋欄輸入文字的狀態。
* **isSearching**：布林狀態，表示是否正在進行搜尋。
* **List<Person>**：人員清單，用作搜尋資料來源。
* **Search Initials**：使用姓名縮寫（如 PL）進行搜尋的功能。
* **Ignore Case**：搜尋時忽略大小寫的條件。
* **Blank Check**：檢查搜尋輸入是否為空字串。
* **List Filtering**：使用條件過濾清單中符合條件的資料。
* **Business Logic**：封裝在資料模型內的邏輯，如搜尋匹配規則。
* **Data Class**：Kotlin 中用於承載資料的特殊類別。
* **Flow Operators**：Kotlin Flow 的轉換與組合操作符集合。
* **UI State Management**：控制 UI 畫面更新所需的狀態邏輯。
* **Reactive Programming**：以資料流與非同步事件驅動應用邏輯的程式設計風格。
* **Collector**：Flow 的資料接收者，一般在 UI 中使用。
* **Caching**：保留最近一次的資料值，避免重複運算。
* **Local Search**：不需 API 請求、僅於裝置端執行的搜尋邏輯。
* **Instant Search**：使用者輸入時即時顯示搜尋結果的功能。
* **TextField onValueChange**：監聽輸入文字變更的事件。
* **Flexible Implementation**：具彈性的架構設計，便於後續擴充與調整。
* **Network Query Optimization**：避免每個字元都觸發請求的策略。
* **Input Throttling**：限制輸入觸發頻率的技術（如 debounce）。
* **Exposed State**：提供 UI 存取但不可變更的狀態。
* **Backpressure Handling**：避免過多資料流導致效能問題的處理機制。
* **UI Responsiveness**：保持使用者介面流暢度的技術與策略。
* **Functional Separation**：將邏輯分層以提升維護性與測試性。
* **Immutable Data**：避免資料被非預期修改以增強穩定性。
* **Search Result Mapping**：將搜尋邏輯轉換為實際顯示資料。
* **State Conversion**：將 Flow 轉為 StateFlow 以便與 UI 綁定。
* **Lambda Expression**：Kotlin 中的匿名函式，用於簡潔表示邏輯區塊。
* **Default Persons**：預設展示的資料，用於初始化資料集。
* **Domain Layer**：專案中負責業務邏輯的程式層級。
* **OnSearchTextChange Function**：用於更新搜尋文字狀態的事件處理器。
* **Dynamic Filtering**：根據使用者輸入即時過濾資料的機制。
* **Modular Logic**：可重用與擴展的邏輯模組設計。
* **Scoped Flow Lifecycle**：根據訂閱狀態控制資料流生命週期。
* **MainActivity**：Android 應用程式的主要進入點 Activity，負責建立 UI 結構。
* **Column**：Jetpack Compose 中垂直堆疊元件的佈局容器。
* **Modifier.fillMaxSize()**：讓元件填滿可用的最大空間。
* **TextField**：允許使用者輸入文字的 UI 元件。
* **ViewModel()**：Compose 中透過 `viewModel()` 取得 ViewModel 實例的方法。
* **collectAsState()**：將 Flow 或 StateFlow 轉為 Compose 可觀察狀態的擴充函數。
* **Placeholder**：輸入欄位中在無內容時顯示的提示文字。
* **Spacer**：Compose 中用於製造空白間距的元件。
* **Dp (Density-independent Pixel)**：Android 中獨立於裝置密度的尺寸單位。
* **LazyColumn**：Compose 中具效能優化的垂直清單元件，僅載入可見項目。
* **items{}**：LazyColumn 用來綁定資料清單的區塊。
* **Text()**：Compose 中用來顯示文字的基本元件。
* **Padding**：設定元件內部或外部的間距。
* **Weight Modifier**：讓元件佔據剩餘空間的修飾符。
* **Emulator**：模擬 Android 裝置的工具，用於測試應用程式。
* **Instant Search**：輸入即時產生搜尋結果的功能。
* **Network Call**：應用程式向網路 API 發出請求以取得資料的行為。
* **HTTP Call**：透過 HTTP 協議與伺服器進行資料交換。
* **Database Query**：從資料庫中查詢特定資料的動作。
* **Debounce Operator**：Flow 操作符，用來延遲資料發送，避免頻繁觸發。
* **@OptIn**：用於啟用實驗性 API 的 Kotlin 標註。
* **onEach{}**：Flow 操作符，對每筆資料進行副作用操作（例如更新狀態）。
* **update{}**：安全更新 MutableStateFlow 的方法，避免多執行緒競爭問題。
* **Box**：Compose 的通用容器元件，常用於疊放或居中對齊內容。
* **CircularProgressIndicator**：顯示加載狀態的圓形進度條。
* **Alignment.Center**：將元件對齊至容器中央的參數。
* **Artificial Delay**：模擬網路延遲或其他等待時間的技巧（例如 `delay(2000)`）。
* **Real-life Scenario**：真實應用場景，用於驗證功能是否符合需求。
* **Simulate API Call**：模擬 API 請求過程以測試搜尋行為。
* **State-driven UI**：以狀態改變為驅動的 UI 架構模式。
* **Conditional UI Rendering**：根據狀態決定是否顯示特定元件。
* **isSearching State**：表示搜尋是否進行中的布林狀態，用於切換顯示元件。
* **Search Delay**：搜尋前暫停一定時間，提升效能與使用體驗。
* **Flow Lifecycle**：資料流的生命週期管理，例如訂閱、取消與快取。
* **Search Result UI**：顯示搜尋結果的使用者介面。
* **Data-binding**：將 UI 與資料狀態同步的機制。
* **Reactive Search**：根據輸入即時更新結果的反應式搜尋模式。
* **Live Search Feedback**：即時提供搜尋進度的視覺回饋。
* **Thread-safe Update**：保證在多執行緒下更新資料的安全機制。
* **TextField.onValueChange**：監聽使用者文字輸入變化的事件。
* **Initial UI State**：UI 啟動時的預設狀態與資料顯示。
* **Delayed Execution**：延遲執行某些邏輯以減少資源浪費。
* **Compose Lifecycle Integration**：Compose 與 ViewModel 生命週期整合的機制。
* **List Mapping**：將資料轉換為對應 UI 元件清單。
* **Center-aligned Loading**：將加載圖示置中顯示於畫面。
* **Scoped ViewModel**：與畫面生命週期綁定的 ViewModel 實例。
* **Loading Animation**：用於表示資料載入過程的動態視覺元件。
* **UI Optimization**：提升 UI 效能與使用者體驗的設計手法。
* **User Input Handling**：處理使用者輸入與互動的邏輯。
* **Search Efficiency**：透過延遲與過濾提升搜尋效能與精確度。
* **Composable Conditional Rendering**：根據條件動態切換元件的組合邏輯。
