管理及更新 GlanceAppWidget

以下各節說明如何更新 GlanceAppWidget 及管理其狀態。

管理「GlanceAppWidget」狀態

每當建立小工具或需要更新時,提供的 GlanceAppWidget 類別都會例項化,因此應是「無狀態和被動式」

狀態的概念可分為以下幾個:

  • 應用程式狀態:小工具需要的應用程式狀態或內容。例如,使用者定義的已儲存目的地 (即資料庫) 清單。
  • Glance 狀態:只與應用程式小工具相關且不一定需要修改或影響應用程式狀態的特定狀態。例如,您在小工具中選取了核取方塊,或計數器已增加。

使用應用程式狀態

應用程式小工具應是被動式。每個應用程式都負責管理資料層和處理狀態,例如閒置、載入中,以及小工具 UI 反映的錯誤。

舉例來說,以下程式碼會從存放區層從記憶體內快取擷取目的地、提供已儲存的目的地清單,並根據其狀態顯示不同的 UI:

class DestinationAppWidget : GlanceAppWidget() {

    // ...

    @Composable
    fun MyContent() {
        val repository = remember { DestinationsRepository.getInstance() }
        // Retrieve the cache data everytime the content is refreshed
        val destinations by repository.destinations.collectAsState(State.Loading)

        when (destinations) {
            is State.Loading -> {
                // show loading content
            }

            is State.Error -> {
                // show widget error content
            }

            is State.Completed -> {
                // show the list of destinations
            }
        }
    }
}

只要狀態或資料有所變更,應用程式就負責通知及更新小工具。詳情請參閱「更新 GlanceAppWidget」。

更新「GlanceAppWidget

如「管理 GlanceAppWidget 狀態」一節所述,應用程式小工具是由不同的程序代管。Glance 會將內容轉譯為實際的 RemoteViews,並傳送至主機。如要更新內容,Glance 必須重新建立 RemoteViews 並再次傳送。

如要傳送更新,請呼叫 GlanceAppWidget 例項的 update 方法,並提供 contextglanceId

MyAppWidget().update(context, glanceId)

如要取得 glanceId,請查詢 GlanceAppWidgetManager

val manager = GlanceAppWidgetManager(context)
val widget = GlanceSizeModeWidget()
val glanceIds = manager.getGlanceIds(widget.javaClass)
glanceIds.forEach { glanceId ->
    widget.update(context, glanceId)
}

或者,使用下列任一 GlanceAppWidget update 擴充功能:

// Updates all placed instances of MyAppWidget
MyAppWidget().updateAll(context)

// Iterate over all placed instances of MyAppWidget and update if the state of
// the instance matches the given predicate
MyAppWidget().updateIf<State>(context) { state ->
    state == State.Completed
}

您可以透過應用程式的任何部分呼叫這些方法。由於這些是 suspend 函式,建議您將其從主執行緒範圍外啟動。在以下範例中,它們會在 CoroutineWorker 中啟動:

class DataSyncWorker(
    val context: Context,
    val params: WorkerParameters,
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        // Fetch data or do some work and then update all instance of your widget
        MyAppWidget().updateAll(context)
        return Result.success()
    }
}

如要進一步瞭解協同程式,請參閱 Android 上的 Kotlin 協同程式