У меня ContentProvider
из основного приложения. Контент будет доступен для пользовательского приложения. В этом потребительском приложении есть виджет приложения. Я протестировал ContentProvider
и ContentObserver
этого потребительского приложения в его Activity, и все в порядке (это означает, что RecyclerView
Activity обновляется всякий раз, когда обновление из основного приложения вызывает изменения в базе данных). Однако регистрация ContentObserver
внутри моего AppWidgetProvider
не работает должным образом.
Мой AppWidgetProvider
имеет следующий код.
class StackWidgetProvider : AppWidgetProvider() {
override fun onEnabled(context: Context) {
Timber.i("Enabled")
if (favoriteUserProviderObserver == null) {
val appWidgetManager = AppWidgetManager.getInstance(context)
val componentName = ComponentName(context, StackWidgetProvider::class.java)
favoriteUserProviderObserver = FavoriteUserProviderObserver(appWidgetManager, componentName).let {
context.contentResolver.registerContentObserver(CONTENT_URI, true, it)
it
}
}
}
override fun onDisabled(context: Context) {
Timber.i("Disabled")
favoriteUserProviderObserver?.let {
context.contentResolver.unregisterContentObserver(it)
}
favoriteUserProviderObserver = null
}
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
....
companion object {
private var favoriteUserProviderObserver: FavoriteUserProviderObserver? = null
private fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int
) {
val intent = Intent(context, StackWidgetService::class.java).apply {
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
data = toUri(Intent.URI_INTENT_SCHEME).toUri()
}
val views = RemoteViews(context.packageName, R.layout.widget_favorite_user_stack).apply {
setRemoteAdapter(R.id.widget_favorite_user_stack_view, intent)
setEmptyView(R.id.widget_favorite_user_stack_view, R.id.widget_favorite_user_empty)
}
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
Я создал простой пользовательский ContentObserver
класс, как показано ниже.
class FavoriteUserProviderObserver(
private val appWidgetManager: AppWidgetManager,
private val componentName: ComponentName
) : ContentObserver(null) {
override fun onChange(selfChange: Boolean) {
Timber.i("Provider observer triggered")
appWidgetManager.notifyAppWidgetViewDataChanged(
appWidgetManager.getAppWidgetIds(componentName), R.id.widget_favorite_user_stack_view
)
}
}
Указанный выше класс наблюдателя никогда не запускается (даже когда я изменяю данные в своем основном приложении). Для большей ясности вот код для моего RemoteViewsService
и его фабрики.
class StackWidgetService : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory =
StackRemoteViewsFactory(this.applicationContext)
}
class StackRemoteViewsFactory(private val context: Context) :
RemoteViewsService.RemoteViewsFactory {
private var widgetItems = listOf<UserProfileSummary>()
private lateinit var repository: FavoriteUserRepository
override fun onCreate() {
repository = FavoriteUserRepository(
FavoriteUserDataSource(context.contentResolver),
Dispatchers.IO
)
}
override fun onDataSetChanged() {
GlobalScope.launch {
widgetItems = repository.favoriteUsers().toList() // Tested; working on the Activity scope of the consumer app
Timber.i(widgetItems.toString())
}
}
override fun getViewAt(position: Int): RemoteViews =
RemoteViews(context.packageName, R.layout.widget_favorite_user_item).apply {
setTextViewText(R.id.widget_favorite_user_item_text, widgetItems[position].username)
}
override fun getLoadingView(): RemoteViews? = null
override fun getItemId(position: Int): Long = 0
override fun hasStableIds(): Boolean = false
override fun getCount(): Int {
return widgetItems.size
}
override fun getViewTypeCount(): Int = 1
override fun onDestroy() {}
}
Итак, logi c - это запрос ContentObserver
на наблюдение изменений в ContentProvider
. Наблюдатель зарегистрирован в onEnabled
и onDisabled
части AppWidgetProvider
. Как только наблюдатель заметит изменение в ContentProvider
, он попросит AppWidgetProvider
обновить себя, таким образом вызывая onDataSetChanged
и получая новый список данных.
Однако наблюдатель никогда не вызывается. Что может быть причиной того, что здесь он работает не так, как ожидалось? (Это не может быть из-за отсутствия разрешения, потому что часть Activity в приложении-потребителе может без проблем получать данные.)