0

I want to update my Glance App Widget state inside CoroutineWorker:

class MyWorker(appContext: Context, workerParams: WorkerParameters) :
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        val glanceId = GlanceAppWidgetManager(applicationContext).getGlanceIds(MyWidget::class.java).first()

        updateAppWidgetState(
            context = applicationContext,
            glanceId = glanceId,
        ) { preferences ->
            preferences.toMutablePreferences().apply{
                this[stringPreferencesKey(TASK_ID)] = id.toString()
            }
        }
            
        MyWidget().updateAll(applicationContext)
        return Result.success()
    }
}

This worker ends with success, but widget state is not updated.

class MyWidget : GlanceAppWidget() {

    override val stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition

    @Composable
    override fun Content() {
        val context = LocalContext.current
        val preferences = currentState<Preferences>()

        val taskId = preferences[stringPreferencesKey(TASK_ID)]
        if (taskId.isNullOrEmpty()) {
            val myWorker = OneTimeWorkRequestBuilder<MyWorker>().build()
            WorkManager.getInstance(context).enqueue(myWorker)

            LoadingScreen()
            return
        }

        // handle finished worker
    }

    @Composable
    fun LoadingScreen() {
        // compose loading screen
    }
}

I tested this code with single widget and it always shows loading screen and taskId is always null even though workers run successfully. How to fix this problem?

1 Answers1

0

So, the problem is in the toMutablePreferences, all of the examples I've seen used this method, however instead of saving new values to the same data store it creates a copy of data store which is not saved.

The correct code should be:

        updateAppWidgetState(
            context = applicationContext,
            glanceId = glanceId,
        ) { preferences ->
            preferences.apply{
                this[stringPreferencesKey(TASK_ID)] = id.toString()
            }
        }
  • Correct, this method already takes the Preferences and makes them mutable for you so you can directly modify its attributes. Check https://developer.android.com/reference/kotlin/androidx/glance/appwidget/state/package-summary – Marcel Jun 08 '22 at 03:28
  • btw, you skip the apply, you can directly call `preferences[string...] = id.toString()` – Marcel Jun 08 '22 at 03:30