更新小部件列表视图

Posted

技术标签:

【中文标题】更新小部件列表视图【英文标题】:Updating Widget Listview 【发布时间】:2016-08-16 19:29:58 【问题描述】:

在我的小部件中,我有一个刷新按钮,用于告诉(自定义)列表视图数据集已更改。现在,我在单击刷新按钮时调用了我的 onRecieve 回调,但是传递的意图包为空,因此我无法在 ID 上调用 onUpdate。

我检查了我添加附加功能的函数,它说它添加的整数数组的长度为 1 且非 null,我不确定为什么这不起作用:/ 希望这里有人可以帮我.

谢谢。

WidgetProvider.java

public class WidgetProvider extends AppWidgetProvider 

    @Override
    public void onDeleted(Context context, int[] appWidgetIds)
    
        super.onDeleted(context, appWidgetIds);
    

    @Override
    public void onDisabled(Context context)
    
        super.onDisabled(context);
    

    @Override
    public void onEnabled(Context context)
    
        super.onEnabled(context);
    

    @Override
    public void onReceive(Context context, Intent intent)
    
        System.out.println("RECIEVED SOMETHING:" + intent.getAction());
        AppWidgetManager appWidgetMgr = AppWidgetManager.getInstance(context);

        Bundle extras = intent.getExtras();
        int[] ids = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); //NPE ON THIS LINE, EXTRAS IS NULL

        System.out.println("SENDING AN UPDATE");
        onUpdate(context, appWidgetMgr, ids);

        super.onReceive(context, intent);
    

    protected PendingIntent getPendingSelfIntent(Context context, String action, int[] ids) 
        Intent intent = new Intent(context, getClass());
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
        System.out.println("PUTTING ARRAY OF LEN: " + ids.length);
        intent.setAction(action);
        return PendingIntent.getBroadcast(context, 0, intent, 0);
    

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                         int[] appWidgetIds)
    
        for(int i=0;i<appWidgetIds.length;i++)
        
            System.out.println("CHECK");
            RemoteViews rv = new RemoteViews(context.getPackageName(),
                    R.layout.app_widget);

            Intent intent = new Intent(context, WidgetService.class);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    appWidgetIds[i]);
            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

            rv.setRemoteAdapter(R.id.list, intent);

            rv.setOnClickPendingIntent(R.id.refresh, getPendingSelfIntent(context,
                    "refresh", appWidgetIds));

            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
        
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    

编辑:新的 onRecieve 函数,同样的错误:

    @Override
    public void onReceive(Context context, Intent intent)
    
        if("refresh".equals(intent.getAction())) 
            System.out.println("RECIEVED SOMETHING:" + intent.getAction());
            AppWidgetManager appWidgetMgr = AppWidgetManager.getInstance(context);

            Bundle extras = intent.getExtras();

            int[] ids = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);

            System.out.println("SENDING AN UPDATE");
            onUpdate(context, appWidgetMgr, ids);
        

        super.onReceive(context, intent);
    

【问题讨论】:

【参考方案1】:

如果您查看source for AppWidgetProvider,onReceive() 会首先针对每个标准小部件操作调用,而不仅仅是针对您的自定义代码。您应该将代码包装在 if 检查中,以确保按下的是您的按钮。

// In onReceive()
if ("refresh".equals(intent.getAction())) 
  // Do your code

您还会注意到PendingIntent documentation:

由于这种行为,重要的是要知道两个 Intent 何时被认为是相同的,以便检索 PendingIntent。人们犯的一个常见错误是创建多个 PendingIntent 对象,其 Intent 仅在其“额外”内容上有所不同,期望每次都获得不同的 PendingIntent。这不会发生。 Intent 中用于匹配的部分与 Intent.filterEquals 定义的部分相同。如果您使用两个根据 Intent.filterEquals 等效的 Intent 对象,那么您将获得相同的 PendingIntent。

...

如果您一次只需要一个激活的 PendingIntent 用于您将使用的任何 Intent,那么您也可以使用标志 FLAG_CANCEL_CURRENT 或 FLAG_UPDATE_CURRENT 来取消或修改与您提供的 Intent 相关联的任何当前 PendingIntent。

因此,您还应该将对PendingIntent.getBroadcast() 的调用更新为

return PendingIntent.getBroadcast(context, 0, intent,
  PendingIntent.FLAG_UPDATE_CURRENT);

当然,另一种方法是直接调用 AppWidgetManager#getAppWidgetIds() 并完全跳过设置任何额外内容。

【讨论】:

更新了我的答案:我什至认为你根本不需要设置任何额外内容,现在我再看看你在做什么。 有趣的sn-p,不知道。调整我的 PendingIntent 或使用 getAppWidgetIds 将解决问题。干杯:) @Nathan,有帮助吗?我有同样的问题,它没有帮助。

以上是关于更新小部件列表视图的主要内容,如果未能解决你的问题,请参考以下文章

访问使用列表框中选择的项目更新子表单

使用应用程序更新 ListView 小部件

在颤振列表视图中检测焦点小部件

Android 无法使用列表视图加载主屏幕小部件

如何将列表视图与其他小部件一起使用?

如何创建具有配置活动的应用小部件,并首次对其进行更新?