Android Jetpack Glance 1.0.0: проблемы с обновлением виджетаAndroid

Форум для тех, кто программирует под Android
Anonymous
Android Jetpack Glance 1.0.0: проблемы с обновлением виджета

Сообщение Anonymous »

Я реализую свой первый виджет приложения на базе Jetpack Glance для простого приложения со списком дел, над которым я работаю. Я следую руководству по адресу https://developer.android.com/jetpack/compose/glance, и все в порядке, пока я не дойду до момента, когда мне нужно обновить свой виджет, чтобы он соответствовал обновлениям данных, произошедшим в моем приложении. .
Насколько я понимаю, управление и обновление GlanceAppWidget, можно вызвать рекомпозицию виджета, вызвав методы update, updateIf или updateAll на экземпляр виджета из самого кода приложения. В частности, вызовы этих функций должны запускать метод GlanceAppWidget.provideGlance(context: Context, id: GlanceId), который отвечает за получение любых необходимых данных и предоставление содержимого виджета, как описано в этом фрагменте кода:

Код: Выделить всё

class MyAppWidget : GlanceAppWidget() {

override suspend fun provideGlance(context: Context, id: GlanceId) {

// In this method, load data needed to render the AppWidget.
// Use `withContext` to switch to another thread for long running
// operations.

provideContent {
// create your AppWidget here
Text("Hello World")
}
}
}
Но в моем случае это не всегда работает. Вот что я заметил после нескольких попыток:
  • Это всегда работает при первом добавлении виджета на мою панель управления. Данные там всегда свежие.
  • Это всегда срабатывает при первом вызове метода обновления из самого приложения (я использую updateAll). Виджет обновляется и отображает актуальные данные.
  • Тогда он не будет работать, если я вызову метод обновления слишком скоро после последнего вызова. В этом случае метод ProvideGlance вообще не срабатывает.
Затем я просмотрел исходный код GlanceAppWidget и заметил это. опирается на класс AppWidgetSession:

Код: Выделить всё

    /**
* Internal version of [update], to be used by the broadcast receiver directly.
*/
internal suspend fun update(
context: Context,
appWidgetId: Int,
options: Bundle? = null,
) {
Tracing.beginGlanceAppWidgetUpdate()
val glanceId = AppWidgetId(appWidgetId)
if (!sessionManager.isSessionRunning(context, glanceId.toSessionKey())) {
sessionManager.startSession(context, AppWidgetSession(this, glanceId, options))
} else {
val session = sessionManager.getSession(glanceId.toSessionKey()) as AppWidgetSession
session.updateGlance()
}
}
Если сеанс запущен, он будет использоваться для запуска обновления виджета Gloss. В противном случае он будет запущен и использован для той же цели.
Я заметил, что моя проблема возникает тогда и только тогда, когда запущен только сеанс, что объясняет, почему этого не происходит, если я дайте ему достаточно времени между обновлениями call : больше нет запущенных сеансов (что бы это ни значило), и необходимо создать новый.
Я попытался покопаться дальше во внутренних компонентах Glance, чтобы понять, почему он не работает при использовании работающего сеанса, но пока безуспешно. Единственное, что я заметил и подумал странно, это то, что в какой-то момент AppWidgetSession внутренне использует класс GlanceStateDefinition, упоминания о котором я не видел в официальном руководстве Android Glance, но который есть в нескольких других руководствах. в Интернете используйте для реализации виджета Glance (хотя и используете альфа- или бета-версии библиотек Jetpack Glance).
Кто-нибудь знает, почему он ведет себя так? Вот дополнительная информация, пожалуйста, дайте мне знать, если вам нужно что-то еще. Большое спасибо!
  • Я использую версию 1.0.0 библиотеки androidx.glance:glance-appwidget, выпущенную несколько дней назад,< /li>
    Я не забыл добавить тег в свой AndroidManifest.xml, а также необходимый android.appwidget.provider xml файл в моей папке res/xml. Я думаю, что я правильно сделал все, что указано на странице настройки Glance, поскольку у меня нет проблем с добавлением виджета на главный экран.
  • Я использую SQLiteOpenHelper под капотом для доступа к моим данным, с несколькими вспомогательными классами, созданными мной поверх них, без использования Room или какой-либо другой библиотеки ORM (пока я хочу, чтобы мое приложение было простым).
  • Вот как выглядит мой метод ProvideGlance:

Код: Выделить всё

    override suspend fun provideGlance(context: Context, id: GlanceId) {

val todoDbHelper = TodoDbHelper(context)
val dbHelper = DbHelper(todoDbHelper.readableDatabase)
val todoDao = TodoDao(dbHelper)
val todos = todoDao.findAll()

provideContent {
TodoAppWidgetContent(todos)
}
}
TodoDao.findAll() возвращает простой список (он опирается на вспомогательную функцию, которая работает на Dispatchers.IO, чтобы основной поток не блокировался )
  • Я также не использую Hilt или любую другую библиотеку DI.


Подробнее здесь: https://stackoverflow.com/questions/770 ... ing-widget

Вернуться в «Android»