While developing my note-taking app and as a new feature I wanna create a widget for my app by jetpack lib glance.
At first, I thought it would be like a normal database implementation, but it didn't work, And I have no idea how it does, even when I made some searches I get only network and API stuff.
But in my case, I wanted the local data.
And here are my classes.
@HiltViewModel
class AppWidgetVM @Inject constructor(
private val repo: EntityRepoImp
): ViewModel() {
private val _allNotesById = MutableStateFlow<List<Entity>>(emptyList())
val allNotesById: StateFlow<List<Entity>>
get() = _allNotesById.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(),
initialValue = listOf()
)
init {
viewModelScope.launch(Dispatchers.IO) {
repo.getAllNotesById.collect {
_allNotesById.value = it
}
}
}
}
@AndroidEntryPoint
class AppWidgetReceiver: GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = AppWidget()
}
class AppWidget: GlanceAppWidget() {
@Composable
override fun Content() {
...
}
}
I know its looks like empty code, But like I said I have no idea how it does.
The variable allNotesById
holds all my local notes, And that is exactly what I want to display in AppWidget class.
So after a long search in public similar apps for my app and depending on favorite-apps-widget project. I finally ended with this solution:
GlanceAppWidget
class AppWidget:GlanceAppWidget() {
@Composable
override fun Content() {
val ctx = LocalContext.current.applicationContext
val viewModel = EntryPoints.get(
ctx,
EntryPoint::class.java
).vm()
WidgetListNotes(ctx = ctx, widgetVm = viewModel)
}
@Composable
fun WidgetListNotes(
ctx: Context,
widgetVm: WidgetVM
) {
...
}
}
EntryPoint
@EntryPoint
@InstallIn(SingletonComponent::class)
interface EntryPoint {
fun vm(): WidgetVM
}
GlanceAppWidgetReceiver
@AndroidEntryPoint
class WidgetReceiver:GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget
get() = AppWidget()
override fun onReceive(context: Context, intent: Intent) {
...
}
WidgetViewModel
class WidgetVM @Inject constructor(
private val widgetEntityRepoImpl: WidgetEntityRepoImpl
) {
@WorkerThread
fun getAllEntities() = widgetEntityRepoImpl.getAllWidgetEntityById
...
}
In MainActivity I decided to update the widget data every pause in the application, you can do it in another place.
...
override fun onPause() {
super.onPause()
WidgetReceiver.updateBroadcast(this)
}
...
Screenshot.
For the rest of the code check my project JetNote.