Android 已调用 updateAppWidget 但未更新小部件或到达 RemoteViewsFactory?

Android updateAppWidget is called but not updating the widget or reaching RemoteViewsFactory?

我的应用程序小部件(显示游戏分数的 ListView)在主屏幕上创建时工作正常,但是当我在提供者内部调用 appWidgetManager.updateAppWidget(id, R.id.appwidget) 时,小部件或 RemoteViewsFactoryonCreate()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 使用了不同的可绘制对象。