具有不同 ListView 数据的相同小部件
Posted
技术标签:
【中文标题】具有不同 ListView 数据的相同小部件【英文标题】:Same widgets with different ListView data 【发布时间】:2018-12-02 05:08:00 【问题描述】:我有一个带有 ListView 的简单 AppWidget。 该小部件具有简单的配置活动,您可以在其中选择要显示的数据集。该信息(int id)存储在 SharedPreferences 中,然后从 RemoteViewsFactory 中的 SP 获取。 一切正常,直到我在屏幕上添加另一个小部件。如果选中,新的不会加载不同的数据,而是从以前的小部件中获取一个。 几乎没有调试,我认为我的 onUpdate 方法没有被调用,但我在这里找不到问题。
WidgetConfig.java
public class IngredientsWidgetConfigureActivity extends Activity implements RecipesAdapter.RecipesAdapterOnClickHandler
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
RecipesAdapter mAdapter;
public IngredientsWidgetConfigureActivity()
super();
//save recipeId into SharedPrefs
static void saveSelectedRecipe (Context context, int appWidgetId, int selectedRecipe)
SharedPreferences.Editor prefs = context.getSharedPreferences(AppConstants.PREFS_NAME, 0).edit();
prefs.putInt(AppConstants.PREF_PREFIX_KEY + appWidgetId, selectedRecipe);
prefs.apply();
@Override
protected void onCreate(@Nullable Bundle icicle)
super.onCreate(icicle);
setResult(RESULT_CANCELED);
setContentView(R.layout.ingredients_widget_configure);
//setup RecyclerView
...
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null)
mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)
finish();
return;
@Override
public void onClick(Recipe recipe)
final Context context = IngredientsWidgetConfigureActivity.this;
// When the button is clicked, store the recipe Id
int selectedRecipe = recipe.id;
saveSelectedRecipe(context, mAppWidgetId, selectedRecipe);
// It is the responsibility of the configuration activity to update the app widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
IngredientsWidget.updateAppWidget(context, appWidgetManager, mAppWidgetId);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
小部件提供者
....
static void updateAppWidget(final Context context, AppWidgetManager appWidgetManager,
int appWidgetId)
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.ingredients_widget_layout);
Intent intent = new Intent(context, WidgetRemoteViewsService.class);
intent.putExtra(AppConstants.APP_WIDGET_ID_KEY, appWidgetId);
views.setRemoteAdapter(R.id.widget_list_view, intent);
//TODO: recipes are not changing in different widgets
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds)
updateAppWidget(context, appWidgetManager, appWidgetId);
最后是我的 RemoteViewsFactory.java
public WidgetRemoteViewsFactory (Context context, Intent intent)
mContext = context;
appWidgetId = intent.getIntExtra(AppConstants.APP_WIDGET_ID_KEY, 1);
@Override
public void onCreate()
@Override
public void onDataSetChanged()
final long identityToken = Binder.clearCallingIdentity();
//get id from SharedPref
RecipeDatabase mDb = RecipeDatabase.getInstance(mContext);
SharedPreferences prefs = mContext.getSharedPreferences(AppConstants.PREFS_NAME, 0);
recipeId = prefs.getInt(AppConstants.PREF_PREFIX_KEY + appWidgetId, 9999);
recipe = mDb.recipeDAO().loadRecipe(recipeId);
Binder.restoreCallingIdentity(identityToken);
@Override
public void onDestroy()
@Override
public int getCount()
if (recipe == null)
return 0;
else
return recipe.ingredients.size();
@Override
public RemoteViews getViewAt(int position)
if (position > recipe.ingredients.size())
return null;
RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.widget_list_item);
remoteViews.setTextViewText(R.id.widget_text, recipe.ingredients.get(position).getIngredient());
return remoteViews;
@Override
public RemoteViews getLoadingView()
return null;
@Override
public int getViewTypeCount()
return 1;
@Override
public long getItemId(int position)
return position;
@Override
public boolean hasStableIds()
return true;
【问题讨论】:
【参考方案1】:解决了... 我必须将新数据放入 updateAppWidget 的 Intent 中,以便工厂加载新实例而不是重用新实例。 所以我用每个小部件发送新的随机值数据,所以它会正确更新。 updateAppWidget sn-p:
//send intent and data to Adapter
Intent intent = new Intent(context, WidgetRemoteViewsService.class);
intent.putExtra(AppConstants.APP_WIDGET_ID_KEY, appWidgetId);
//set random data to initialize new Factory
Random rnd = new Random();
intent.setData(Uri.fromParts("content", String.valueOf(rnd.nextInt()), null));
views.setRemoteAdapter(R.id.widget_list_view, intent);
感谢@TheFedex87
【讨论】:
以上是关于具有不同 ListView 数据的相同小部件的主要内容,如果未能解决你的问题,请参考以下文章
在flutter中使用listview.builder添加多个彼此不同的动态小部件