Android 已调用 updateAppWidget 但未更新小部件或到达 RemoteViewsFactory?
Android updateAppWidget is called but not updating the widget or reaching RemoteViewsFactory?
我的应用程序小部件(显示游戏分数的 ListView)在主屏幕上创建时工作正常,但是当我在提供者内部调用 appWidgetManager.updateAppWidget(id, R.id.appwidget)
时,小部件或 RemoteViewsFactory
的 onCreate()
或 onDataSetChanged()
方法。我知道 updateAppWidget
被调用了,因为我可以看到它之前的日志调用。
为什么小部件没有更新?
我的 AppWidgetProvider:
class ScoresAppWidgetProvider : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
updateAllWidgets(appWidgetIds, context, appWidgetManager)
super.onUpdate(context, appWidgetManager, appWidgetIds)
}
private fun updateAllWidgets(appWidgetIds: IntArray, context: Context, appWidgetManager: AppWidgetManager) {
appWidgetIds.forEach { appWidgetId ->
updateWidget(appWidgetId, context, appWidgetManager, false)
}
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
Log.i("TAG", "onReceive appWidgetId $appWidgetId") // This is logged and id is correct
if (intent.action.equals(ACTION_CLICK_REFRESH)) {
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.appwidget_list_view) // Works fine and updates the widget list
} else if (intent.action.equals((ACTION_CLICK_SPOILERS_ON))) { // This is received
updateWidget(appWidgetId, context, appWidgetManager, true)
} else if (intent.action.equals((ACTION_CLICK_SPOILERS_OFF))) { // This is received
updateWidget(appWidgetId, context, appWidgetManager, false)
}
}
private fun updateWidget(appWidgetId: Int, context: Context, appWidgetManager: AppWidgetManager, spoilers: Boolean) {
val intent = Intent(context, AppWidgetService::class.java).apply {
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
putExtra("testString", "Intent received")
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
}
// PendingIntent to refresh the appWidget contents
val pendingRefreshClickIntent: PendingIntent = Intent(context, ScoresAppWidgetProvider::class.java).let {
it.action = ScoresAppWidgetProvider.ACTION_CLICK_REFRESH
it.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
return@let PendingIntent.getBroadcast(context, appWidgetId, it, PendingIntent.FLAG_UPDATE_CURRENT)
}
// PendingIntent to toggle score spoilers
val pendingSpoilersClickIntent: PendingIntent = Intent(context, ScoresAppWidgetProvider::class.java).let {
it.action = if (spoilers) ScoresAppWidgetProvider.ACTION_CLICK_SPOILERS_ON else ScoresAppWidgetProvider.ACTION_CLICK_SPOILERS_ON
it.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
return@let PendingIntent.getBroadcast(context, appWidgetId, it, PendingIntent.FLAG_UPDATE_CURRENT)
}
// RemoteViews object for the app widget layout
val remoteViews = RemoteViews(context.packageName, R.layout.appwidget).apply {
if (spoilers) {
setImageViewResource(R.id.btn_spoilers, R.drawable.avd_anim_turn_off_spoilers)
} else {
setImageViewResource(R.id.btn_spoilers, R.drawable.avd_anim_turn_on_spoilers)
}
setRemoteAdapter(R.id.appwidget_list_view, intent)
setEmptyView(R.id.appwidget_list_view, R.id.empty_view)
setOnClickPendingIntent(R.id.btn_refresh, pendingRefreshClickIntent)
setOnClickPendingIntent(R.id.btn_spoilers, pendingSpoilersClickIntent)
}
Log.i(TAG, "updateWidget: Calling updateWidget!") // This is logged
appWidgetManager.updateAppWidget(appWidgetId, remoteViews) // NO EFFECT FROM THIS CALL!!
}
}
我的 RemoteViewsService 和 RemoteViewsFactory:
class AppWidgetService: RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return ListRemoteViewsFactory(this.applicationContext, intent)
}
class ListRemoteViewsFactory(private val context: Context, val intent: Intent): RemoteViewsFactory {
...
override fun onCreate() {
Log.i(TAG, "onCreate: created!") // Logged when I add the widget first time, not logged when I call updateAppWidget() from AppWidgetProvider
updateList()
}
override fun onDataSetChanged() {
Log.i(TAG, "onDataSetChanged: changed!")
updateList()
}
...
}
}
似乎传递给 remoteViews 的布局被缓存了,你必须使用不同的布局才能工作。我使用了两种不同的布局来更新基于布尔值的小部件,并且它起作用了。
val remoteViews = if (spoilers) RemoteViews(context.packageName, R.layout.appwidget_spoilers) else RemoteViews(context.packageName, R.layout.appwidget_no_spoilers)
布局可以相似,但必须有一些差异。在我的例子中,我为 ImageView 使用了不同的可绘制对象。