为每个小部件提供唯一数据

Posted

技术标签:

【中文标题】为每个小部件提供唯一数据【英文标题】:Giving each widget unique data 【发布时间】:2015-02-28 09:09:10 【问题描述】:

我希望用户能够创建每个都有自己状态的小部件(具体来说,每个小部件很可能是唯一的两个整数)。单击小部件时,整数将用于执行某些操作。我想我可以通过将数据作为附加内容添加到意图并使用 setOnClickPendingIntent() 方法为每个小部件提供唯一的意图来做到这一点。但是,似乎这最终会为每个小部件提供与初始小部件相同的配置。下面是一些相关代码:

WidgetConfig.java - “保存小部件”按钮的 onClick() 方法

@Override
public void onClick(View view) 

    int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;

    Bundle extras = getIntent().getExtras();
    if(extras != null)
        mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
                                     AppWidgetManager.INVALID_APPWIDGET_ID);

    AppWidgetManager manager = AppWidgetManager.getInstance(getApplicationContext());

    RemoteViews views = new RemoteViews(getApplicationContext().getPackageName(), R.layout.appwidget_layout);

    //pass data to service using intent
    Intent newIntent = new Intent(getApplicationContext(), FilterService.class);
    newIntent.putExtra("alpha", 255 - alpha);
    newIntent.putExtra("red", red);

    Log.e("WidgetConfig", "Put in alpha: " + newIntent.getIntExtra("alpha", -1) + ", red: " + newIntent.getIntExtra("red", -1));

    //set intent to be executed when widget is clicked and update widget
    PendingIntent pending = PendingIntent.getService(getApplicationContext(), 0, newIntent, 0);
    views.setOnClickPendingIntent(R.id.ivWidget, pending);

    manager.updateAppWidget(mAppWidgetId, views);

    //Pass result back to OS to create widget
    Intent resultVal = new Intent();
    resultVal.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
    setResult(RESULT_OK, resultVal);
    finish();

FilterService.java - 这是我要恢复数据的 onStartCommand() 方法

@Override
public int onStartCommand(Intent intent, int flags, int startId) 

    int alpha = intent.getIntExtra("alpha", 256);
    int red = intent.getIntExtra("red", 256);
    Log.e("FilterService", "alpha = " + alpha);
    Log.e("FilterService", "red = " + red);

logcat 输出如下所示:

E/WidgetConfig: Put in alpha: 143, red: 105
E/FilterService: alpha = 143
E/FilterService: red = 105
E/WidgetConfig: Put in alpha: 9, red: 254
E/FilterService: alpha = 143
E/FilterService: red = 105

此代码适用于第一个小部件,但之后添加的所有小部件都会收到相同的附加意图。我错过了什么吗?或者有没有更好的方法给小部件提供他们需要的数据?

【问题讨论】:

【参考方案1】:

这是一个非常普遍的问题——我怀疑大多数小部件开发人员都遇到过这个问题。 PendingIntent 概述的后半部分解释说,正如您所发现的,仅更改意图中的额外内容不会导致 android 生成单独的 PendingIntent: http://developer.android.com/reference/android/app/PendingIntent.html

正如文档所说,有不同的方法可以解决这个问题。我使用的一种方法是将额外数据放入 URI,并将该 URI 设置为意图的数据。我认为下面的代码会起作用,尽管在我的应用程序中,除了查询参数之外,我还有 URI 的其他部分。但至少通过一些调整它应该可以工作:

Intent newIntent = new Intent(getApplicationContext(), FilterService.class);
Uri.Builder builder = new Uri.Builder();
builder.appendQueryParameter("alpha", Integer.toString(255 - alpha));
builder.appendQueryParameter("red", Integer.toString(red));
newIntent.setData(builder.build());

那么在你的服务中,你会这样做:

int alpha;
int red;
Uri uri = intent.getData();
if (uri != null) 
    try 
        alpha = Integer.parseInt(uri.getQueryParameter("alpha"));
        red = Integer.parseInt(uri.getQueryParameter("red"));
     catch (NumberFormatException e) 
        //TODO either ignore or have default alpha / red values
    

【讨论】:

以上是关于为每个小部件提供唯一数据的主要内容,如果未能解决你的问题,请参考以下文章

是否可以为 Text 小部件提供默认值?

Flutter - 我可以用 Hero 包装每个小部件来为它们设置动画吗

为移动应用程序的 UI 小部件选择库

各种屏幕的标准小部件尺寸

Kivy:获取小部件 ID 并通过唯一属性访问小部件

带有 ListView 的小部件为找到的每个项目显示“正在加载”