Hey :thinking_face: Do y'all know if it's possible...
# glance
d
Hey 🤔 Do y'all know if it's possible to have a single
GlanceStateDefinition
shared across multiple instances of the same widget?
p
I do not think this is possible. As i understand, the state is connected with glanceID. Every insurance of a widget have their own
d
🤔 I think I got the wrong idea about this, I thought we were supposed to use that to save all data needed to display the widget in the
GlanceStateDefinition
I thought we needed to load the data needed to populate the widget in a service or somewhere else in the application, then using transfer everything to the
GlanceStateDefinition
data store
p
Yes and Yes 🙂 . Maybe I misunderstood your question. I thought that you want to use same StateDefinition for all the instances of
MyWidget::class
d
You understood my correctly. I wanted to do what you just said. In my previous widgets we just used a single data store for all of our widgets (same as the application's). We'd inject the data store in the
RemoteViewsService
then update it in
RemoteViewsService.RemoteViewsFactory
it has always been confusing with a lot of steps...
Now it seems easier but I'm just not sure about the proper way to load data from our database to populate the widgets. Having to copy over to the definitions seems odd
p
You can start worker that has the store injected, then call updateWidget from it
p
Sorry, that state was meant only to store UI-only state, not application state.
Similar to what
rememberSaveable
would be used for, but adapted for Glance instances
d
say I have something like:
Copy code
data class Thing(val label: String, val id: Long)
and my widget renders
List<Thing>
, wouldn't be ok to save this list in the widget state (aka the
GlanceStateDefinition
)? Otherwise, how would we do it?
m
@daivid Could you handle it? I need something like this.
d
@Mehmet Peker what we ended up doing was: 1. save the data needed to populate the widget in some other storage X (other than the
GlanceStateDefinition
), we tried both a data store and room. 2. created a helper that loads the data from X and maps it to the
GlanceStateDefinition
for each widget 3. we call the helper every time the data is updated to make sure the widget is updated
m
@daivid Do you have a code example?I would be very happy if you could share it with me.
I have saved my data in datastore but i can't save to glance state definition.
Or is there a way access DataStore data from glance widget.
d
Hey @Mehmet Peker something more or less like this:
Copy code
interface WidgetStateManager<T> : WidgetStateProvider<T> {
    suspend fun persist(preferences: Preferences, data: T?): Preferences
    suspend fun load(): T?
}

suspend inline fun Context.updateMyWidget(myWidgetStateManager: WidgetStateManager) {
    val data = myWidgetStateManager.load() // imagine WidgetStateManager uses a DataStore<Preferences> internally
    val glanceIds = GlanceAppWidgetManager(this).getGlanceIds(MyGlanceWidget::class.java)

    for (glanceId in glanceIds) {
        updateAppWidgetState(this, PreferencesGlanceStateDefinition, glanceId) { state: Preferences ->
            myWidgetStateManager.persist(state, data) // WidgetStateManager here works as a helper function, mapping the loaded data to the widget's preferences state definition
        }
        MyGlanceWidget().update(this, glanceId)
    }
}
In your widget you could have something like this:
Copy code
@Composable
fun MyWidget() {
  val widgetPrefState = currentState<Preferences>
  val widgetData = widgetPrefState.mapToWidgetData()
}
Not the most intuitive, but it works ok-ish
m
@daivid My implementation is here.I wonder to your implantation.Can you explain how to your persist function work?How do you convert model to state?https://github.com/mehmetpeker/Jetpack-Glance-Reddit-Widget
d
hey @Mehmet Peker my persist is just mapping data from the application data store to the widget preferences
🙌 1