簡體   English   中英

如何將僅在運行時已知的參數注入 Android Worker?

[英]How to inject parameters into Android Worker that are only known at runtime?

目標

如何將myObjectmyClass參數傳遞給下面的GlanceWorker

背景

我正在使用android-workmanager來運行后台任務。 這些任務是從我用Glance添加的主屏幕小部件初始化的。 按照 Google 此處的建議(請參閱“我如何獲取數據?”),我使用 worker 來更新從ActionCallback啟動的 Glance 可組合項。

要更新我的小部件,worker 構造函數需要采用兩個額外的參數myObjectmyClass (除了contextworkerParameters )。 到目前為止,我讀過的所有示例都提到了使用WorkerFactory來實現這一點。 這個額外的參數總是在啟動時提供給工廠或通過匕首圖注入。

但是,在我的例子中,這些額外參數的類型取決於哪個小部件啟動了ActionCallback (每個小部件都有自己的GlanceStateDefinition()GlanceAppWidget()擴展)。 因此,我只能在運行時向工作人員提供額外的參數(據我所知)並且不知道如何將它預先提供給自定義WorkerFactory 為了使它更復雜,我的一個額外參數使用了通用T

abstract class Action<T : ShowPortfolioMenuState<T>>(
    val myObject: GlanceStateDefinition<T>,
    val myClass: Class<out WidgetAbstractClass>,
) : ActionCallback {

    override suspend fun onAction(
        context: Context,
        glanceId: GlanceId,
        parameters: ActionParameters,
    ) {
        val glanceIdInt = GlanceAppWidgetManager(context).getAppWidgetId(glanceId)
        val showMenu = parameters[ActionParameters.Key("showMenu")] ?: false

        val glanceWork =
            OneTimeWorkRequest.Builder(GlanceWorkerPortfolioChange::class.java)
                .setInputData(
                    workDataOf("GLANCE_ID" to glanceIdInt, "SHOW_MENU" to showMenu)
                ).build()

        WorkManager.getInstance(context)
            .beginUniqueWork("Worker Name",
                ExistingWorkPolicy.REPLACE,
                glanceWork
            ).enqueue()
    }
}
@HiltWorker
class GlanceWorker<T: ShowMenuState<T>> @AssistedInject constructor(
    @Assisted val context: Context,
    @Assisted workerParameters: WorkerParameters,
    val myObject: GlanceStateDefinition<T>, /*<--- how do i add to constructor*/
    val myClass: Class<out WidgetAbstractClass>, /*<--- how do i add to constructor*/
    ): CoroutineWorker(context, workerParameters) {
    
    override suspend fun doWork(): Result {
        val glanceIdInt = inputData.getInt("GLANCE_ID", -1)
        val glanceId = GlanceAppWidgetManager(context).getGlanceIdBy(glanceIdInt)
        val showMenu = inputData.getBoolean("SHOW_MENU", false)

        myClass.apply {
            updateAppWidgetState(context, myObject, glanceId) { state -> /*state is of type T*/
                state.updateShowMenu(showMenu)
            }
            update(context, glanceId)
        }
        return Result.success()
    }
}

幾件事:

  1. 動作不能帶參數。 Glance 將無法實例化 class 並失敗。 反而:
    1. 使用 ActionParameters 將 Class 名稱作為字符串傳遞,然后使用Class.forName(..)獲取類型/實例。
    2. 使用 GlanceAppWidget 實例獲取 state https://developer.android.com/reference/kotlin/androidx/glance/appwidget/GlanceAppWidget#(androidx.glance.appwidget.GlanceAppWidget).getAppWidgetState(android.content.Context,androidx. glance.GlanceId)
  2. 您可以通過將其作為workData傳遞給工作人員來做同樣的事情

一些工人的例子:

https://github.com/android/user-interface-samples/blob/main/AppWidget/app/src/main/java/com/example/android/appwidget/glance/weather/WeatherWorker.kt

https://github.com/android/user-interface-samples/blob/main/AppWidget/app/src/main/java/com/example/android/appwidget/glance/image/ImageWorker.kt

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM