Я знаю, что это было задано много раз, но я просмотрел документацию сверху донизу, прочитал все ответы здесь, и никто из них не помог. Чтобы быть честным, каждый ответ говорит о чем-то другом о том, как это подходить.Как обновить виджет приложений с видом списка из Activity
Теперь вернемся к моему вопросу. Я хочу обновить вид списка виджетов из некоторой активности, и для этой цели я создал WidgetProvider#sendUpdateBroadcastToAllWidgets()
, который я вызываю из этой операции.
В конечном итоге он вызывает onUpdate()
, поэтому передача принимается правильно. Но взгляды не освежаются.
Я также попытался позвонить AppWidgetManager#notifyAppWidgetViewDataChanged()
и обновил данные в WidgetFactory#onDataSetChanged()
, но метод так и не был вызван.
Так что я думаю, что все это не работает, потому что фабрика удаленных просмотров кэширована, но я не знаю, как это можно преодолеть. Есть предположения?
А как насчет контекстов? Я всегда должен поставлять один, но мне не очень нравится, какой из них. Это имеет значение?
Благодаря
ПРОВАЙДЕР
public class WidgetProvider extends AppWidgetProvider {
public static void sendUpdateBroadcastToAllWidgets(Context context) {
int allWidgetIds[] = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WidgetProvider.class));
Intent intent = new Intent(context, WidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
context.sendBroadcast(intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager widgetManager, int[] widgetIds) {
for (int id : widgetIds) {
updateWidget(context, widgetManager, id);
}
super.onUpdate(context, widgetManager, widgetIds);
}
@Override
public void onDeleted(Context context, int[] widgetIds) {
WidgetPreferences prefs = new WidgetPreferences(context);
for (int widgetId : widgetIds) {
prefs.getWidgetPreferences(widgetId).edit().clear().commit();
}
super.onDeleted(context, widgetIds);
}
private static void updateWidget(Context context, AppWidgetManager widgetManager, int widgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
// set list adapter
Intent serviceIntent = new Intent(context, WidgetService.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
views.setRemoteAdapter(android.R.id.list, serviceIntent);
views.setEmptyView(android.R.id.list, android.R.id.empty);
// set widget title
WidgetDataCategory category = new WidgetPreferences(context).getSavedCategory(widgetId);
views.setTextViewText(R.id.titleText, context.getString(category.titleResourceId()));
// set onclick listener - we create a pending intent template and when an items is clicked
// the intent is filled with missing data and sent
Intent startActivityIntent = new Intent(context, SimplePersonDetailActivity.class);
startActivityIntent.setData(Uri.parse(startActivityIntent.toUri(Intent.URI_INTENT_SCHEME)));
startActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivityIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setPendingIntentTemplate(android.R.id.list, pendingIntent);
// all hail to Google
widgetManager.updateAppWidget(widgetId, views);
}
}
ФАБРИКА
public class WidgetFactory implements RemoteViewsService.RemoteViewsFactory {
private Context context;
private List<Person> people = new ArrayList<>();
public WidgetFactory(Context context, Intent intent) {
this.context = context;
int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (widgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
WidgetPreferences prefs = new WidgetPreferences(context);
WidgetDataCategory category = prefs.getSavedCategory(widgetId);
int numberOfItemsToShow = prefs.getSavedLimit(widgetId);
people = category.filterAndSlice(new PersonDao(context).getAllForGroup(Constants.SIMPLE_GROUP_ID), numberOfItemsToShow);
}
}
@Override
public void onCreate() {}
@Override
public void onDataSetChanged() {}
@Override
public void onDestroy() {}
@Override
public int getCount() {
return people.size();
}
@Override
public RemoteViews getViewAt(int position) {
Person person = people.get(position);
BigDecimal amount = ListViewUtil.sumTransactions(new TransactionDao(context).getAllForPerson(person));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_widget);
remoteViews.setTextViewText(R.id.nameText, person.getName());
remoteViews.setTextViewText(R.id.amountText, MoneyFormatter.withoutPlusPrefix().format(amount));
// fill details for the onclick listener (updating the pending intent template
// set in the WidgetProvider)
Intent listenerIntent = new Intent();
listenerIntent.putExtra(Constants.PERSON_ID, people.get(position).getId());
remoteViews.setOnClickFillInIntent(R.id.widgetItem, listenerIntent);
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;
}
}
У меня должна быть плохая карма или еще что-то. Я сделал это раньше, и это не сработало, но я все равно попробовал его, и он работает :) Спасибо – user219882
И еще одно: недостаточно просто сообщить, что данные изменились. Это одно не работает для нескольких экземпляров виджета. Вам также нужно вызвать 'updateWidget()' или вообще код, который находится в 'onUpdate()' – user219882
, как вы снова код в 'onUpdate()'? – natsumiyu