How can I pass myObject
and myClass
parameters to GlanceWorker
below?
I am using android-workmanager
to run background tasks. These tasks are initialized from a home screen widget which I have added with Glance. As recommended by Google here (see “How do I fetch data?”) I use the worker to update the Glance composable which is started from an ActionCallback
.
To update my widget, the worker constructor needs to take two extra parameters myObject
and myClass
(in addition to context
and workerParameters
). All examples that I have read so far have mentioned the use of a WorkerFactory
in order to achieve this. This extra parameter is always provided to the factory at start-up or injected via the dagger graph.
However, in my case, the type of these extra parameters is dependent on which widget initiated the ActionCallback
(each widget has its own extension of GlanceStateDefinition()
and GlanceAppWidget()
). Therefore I can only provide the extra parameters to the worker at runtime (as far as I'm aware) and don't know how to have it pre-provided to the custom WorkerFactory
. To make it more complicated, one of my extra parameters uses a generic 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()
}
}
A couple of things:
Class.forName(..)
to get the type/instance.workData
Some workers examples: