流程簡介

Home API 的 Kotlin 版本會使用流程,這是 Kotlin 語言的功能,可提供強大的功能來處理非同步資料串流,包括轉換、篩選、對應、轉換至和從集合轉換等。

協同程式與流程密切相關,可提供編寫非同步程式碼的優雅抽象,讓開發人員不必明確編寫回呼例程。流程與協同程式密切配合,可用於非同步方式從協同程式擷取資料,無須等待函式或執行緒完成。

消費者會在「收集」程序中,從資料流中擷取資料。Kotlin 流程有 collect() 函式,可用於此用途。收集期間流程中的情況取決於流程類型。

Kotlin 資料流 (Flow<T>) 預設為,也就是說,只有在呼叫 collect() 時,資料流建構工具程式碼才會產生資料。相反地,流程會立即產生資料,並將資料緩衝在記憶體中,就像佇列一樣,以便在資料使用時讀取。由於熱流會在記憶體中維護資料,因此被視為有狀態。

您可以使用 shareIn 運算子將資料流從冷轉熱 (請參閱「使用 shareIn 將冷資料流轉為熱資料流」)。您也可以使用 SharedFlowStateFlow 將冷資料流轉為熱資料流。

範例應用程式如何使用流程

範例應用程式使用 Jetpack Compose 中的 View 模型,並連結至 Home API 中的流程。許多應用程式範例的 UI 元素都是由狀態驅動,但可以與使用者互動。這個範例應用程式也會在 UI 中將裝置狀態與「樂觀」狀態混合,提供即時的使用者體驗。「樂觀」一詞的意思是應用程式會假設特定動作成功,並立即更新 UI 以反映預期結果,而不會等待確認。如果發現動作失敗,UI 會更新,以反映實際狀態。

在範例應用程式中,系統會為檢視區塊模型的每個層級 (結構、房間、裝置) 建立流程。舉例來說,這會對 GlobalViewModel.kt 中具有下列呼叫的結構體執行此操作:

  fun getStructuresState(): StateFlow<List<StructureModel>?> =
    homeClient
      .structures()
      .map { structures -> structures.map { StructureModel(it.name, it) }.sortedBy { it.name } }
      .handleErrors()
      .flowOn(Dispatchers.IO)
      .stateIn(scope = viewModelScope, started = SharingStarted.WhileSubscribed(), null)

emitAll() 會收集指定資料流中的所有值,並將這些值傳送至收集器。stateIn() 會將上游流程中單一執行中例項的最新發出值,與多個下游訂閱者共用。詳情請參閱 kotlinx.coroutines.flow 參考資料。

Jetpack Compose

如要在本機記憶體中儲存流程物件,並防止其終止,請使用 Kotlin remember API。

在 Jetpack Compose 中,如果您將此功能與 collectAsStateWithLifecycle() 搭配使用,Jetpack 會根據應用程式 UI 顯示該狀態是否實際處於前景,自動管理訂閱和取消訂閱流程。

範例應用程式中的簡單呼叫就能做到這點。使用先前顯示的 getStructuresState() 函式:

val structuresList by
    remember(globalViewModel) { globalViewModel.getStructuresState() }.collectAsStateWithLifecycle()

從現在開始,當結構的任何狀態 (例如 name) 發生變更時,使用該狀態的可組合函式會自動反映更新後的狀態。在範例應用程式中,這個函式為 HomeActivityContent()

資源

如要進一步瞭解 Kotlin、資料流、協同程式和 Jetpack Compose,請參閱下列資源: