在小部件提供程序中接收广播时替换 RemoteViewsFactory
Replace RemoteViewsFactory on receiving a broadcast in widget provider
我有一个带有显示列表视图的小部件的应用程序。我想根据用户在应用程序中打开的食谱更新列表。
首先,当 activity 打开时,我会发送一个带有额外整数的广播。
然后在小部件提供程序中,我使用包含从广播接收到的整数的意图设置远程适配器。
现在我希望每次都创建新的 RemoteViewsFactory,这样我就可以从意图中提取一个整数并根据这个数字加载不同的列表。
问题是这只会在应用程序首次打开时发生,每隔一段时间只会调用 MyWidgetRemoteViewsFactory 中的 onDataSetChanged(),所以我无法获取配方编号以正确更新数据。小部件中的列表永远不会更新。
如何强制小部件重新创建 RemoteViewsFactory?基于关于 Whosebug 的其他主题,我尝试在 appWidgetManager.updateAppWidget(appWidgetId1, null) 中传递 null - 这没有用。
MainListActivity.java - 发送广播
@Override
public void onItemClickListener(int itemID) {
Intent recipeIntent = new Intent(this, BakingWidgetProvider.class);
recipeIntent.setAction(BakingWidgetProvider.UPDATE_WIDGET_RECIPE);
recipeIntent.putExtra(StepsListActivity.EXTRA_RECIPE_ID, itemID);
sendBroadcast(recipeIntent);
Intent intent = new Intent(MainListActivity.this, StepsListActivity.class);
intent.putExtra(StepsListActivity.EXTRA_RECIPE_ID, itemID);
startActivity(intent);
}
BakingWidgetProvider.java - 接收广播
@Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(UPDATE_WIDGET_RECIPE)) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.baking_widget);
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
int viewIndex = intent.getIntExtra(StepsListActivity.EXTRA_RECIPE_ID, 0);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, BakingWidgetProvider.class));
for (int appWidgetId1 : appWidgetIds) {
//trying to pass null to clear the data ?
appWidgetManager.updateAppWidget(appWidgetId1, null);
}
Intent intent2 = new Intent(context, MyWidgetRemoteViewsService.class);
Bundle bundle = new Bundle();
bundle.putInt(StepsListActivity.EXTRA_RECIPE_ID,viewIndex );
intent2.putExtras(bundle);
remoteViews.setRemoteAdapter(R.id.list_view, intent2);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_view);
//empty view
remoteViews.setEmptyView(R.id.list_view, R.id.empty_view);
for (int appWidgetId1 : appWidgetIds) {
appWidgetManager.updateAppWidget(appWidgetId1, remoteViews);
}
}
super.onReceive(context, intent);
}
MyWidgetRemoteViewsService.java - 从意图中获取整数以正确更新数据
public class MyWidgetRemoteViewsService extends RemoteViewsService {
private static final String MyOnClick = "myOnClickTag";
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new MyWidgetRemoteViewsFactory(this.getApplicationContext(), intent);
}
class MyWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
List<Recipe> recipeList;
private Context mContext;
private int mRecipeOpen;
public MyWidgetRemoteViewsFactory(Context context, Intent intent) {
mRecipeOpen = intent.getExtras().getInt(StepsListActivity.EXTRA_RECIPE_ID);
mContext = context;
}
@Override
public void onCreate() {
}
@Override
public void onDataSetChanged() {
recipeList = AppDatabase.getInstance(getApplicationContext()).recipeDao().getAll();
}
@Override
public void onDestroy() {
}
@Override
public int getCount() {
return recipeList.get(mRecipeOpen).ingredients.size();
}
@Override
public RemoteViews getViewAt(int position) {
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_list_item);
rv.setTextViewText(R.id.quantity, recipeList.get(mRecipeOpen).ingredients.get(position).getQuantity());
rv.setTextViewText(R.id.measurement, recipeList.get(mRecipeOpen).ingredients.get(position).getMeasure());
rv.setTextViewText(R.id.ingredient, recipeList.get(mRecipeOpen).ingredients.get(position).getIngredient());
return rv;
}
@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;
}
}
}
最后我不得不改变方法。
我已将 MyWidgetRemoteViewsFactory 放在单独的 class 中并扩展了 BroadcastReceiver。在 onReceive 方法中,我可以使用从 BakingWidgetProvider 发送的所需整数检索广播。
我有一个带有显示列表视图的小部件的应用程序。我想根据用户在应用程序中打开的食谱更新列表。
首先,当 activity 打开时,我会发送一个带有额外整数的广播。
然后在小部件提供程序中,我使用包含从广播接收到的整数的意图设置远程适配器。
现在我希望每次都创建新的 RemoteViewsFactory,这样我就可以从意图中提取一个整数并根据这个数字加载不同的列表。
问题是这只会在应用程序首次打开时发生,每隔一段时间只会调用 MyWidgetRemoteViewsFactory 中的 onDataSetChanged(),所以我无法获取配方编号以正确更新数据。小部件中的列表永远不会更新。
如何强制小部件重新创建 RemoteViewsFactory?基于关于 Whosebug 的其他主题,我尝试在 appWidgetManager.updateAppWidget(appWidgetId1, null) 中传递 null - 这没有用。
MainListActivity.java - 发送广播
@Override
public void onItemClickListener(int itemID) {
Intent recipeIntent = new Intent(this, BakingWidgetProvider.class);
recipeIntent.setAction(BakingWidgetProvider.UPDATE_WIDGET_RECIPE);
recipeIntent.putExtra(StepsListActivity.EXTRA_RECIPE_ID, itemID);
sendBroadcast(recipeIntent);
Intent intent = new Intent(MainListActivity.this, StepsListActivity.class);
intent.putExtra(StepsListActivity.EXTRA_RECIPE_ID, itemID);
startActivity(intent);
}
BakingWidgetProvider.java - 接收广播
@Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(UPDATE_WIDGET_RECIPE)) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.baking_widget);
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
int viewIndex = intent.getIntExtra(StepsListActivity.EXTRA_RECIPE_ID, 0);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, BakingWidgetProvider.class));
for (int appWidgetId1 : appWidgetIds) {
//trying to pass null to clear the data ?
appWidgetManager.updateAppWidget(appWidgetId1, null);
}
Intent intent2 = new Intent(context, MyWidgetRemoteViewsService.class);
Bundle bundle = new Bundle();
bundle.putInt(StepsListActivity.EXTRA_RECIPE_ID,viewIndex );
intent2.putExtras(bundle);
remoteViews.setRemoteAdapter(R.id.list_view, intent2);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_view);
//empty view
remoteViews.setEmptyView(R.id.list_view, R.id.empty_view);
for (int appWidgetId1 : appWidgetIds) {
appWidgetManager.updateAppWidget(appWidgetId1, remoteViews);
}
}
super.onReceive(context, intent);
}
MyWidgetRemoteViewsService.java - 从意图中获取整数以正确更新数据
public class MyWidgetRemoteViewsService extends RemoteViewsService {
private static final String MyOnClick = "myOnClickTag";
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new MyWidgetRemoteViewsFactory(this.getApplicationContext(), intent);
}
class MyWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
List<Recipe> recipeList;
private Context mContext;
private int mRecipeOpen;
public MyWidgetRemoteViewsFactory(Context context, Intent intent) {
mRecipeOpen = intent.getExtras().getInt(StepsListActivity.EXTRA_RECIPE_ID);
mContext = context;
}
@Override
public void onCreate() {
}
@Override
public void onDataSetChanged() {
recipeList = AppDatabase.getInstance(getApplicationContext()).recipeDao().getAll();
}
@Override
public void onDestroy() {
}
@Override
public int getCount() {
return recipeList.get(mRecipeOpen).ingredients.size();
}
@Override
public RemoteViews getViewAt(int position) {
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_list_item);
rv.setTextViewText(R.id.quantity, recipeList.get(mRecipeOpen).ingredients.get(position).getQuantity());
rv.setTextViewText(R.id.measurement, recipeList.get(mRecipeOpen).ingredients.get(position).getMeasure());
rv.setTextViewText(R.id.ingredient, recipeList.get(mRecipeOpen).ingredients.get(position).getIngredient());
return rv;
}
@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;
}
}
}
最后我不得不改变方法。
我已将 MyWidgetRemoteViewsFactory 放在单独的 class 中并扩展了 BroadcastReceiver。在 onReceive 方法中,我可以使用从 BakingWidgetProvider 发送的所需整数检索广播。