So che è stato chiesto più volte ma ho esaminato la documentazione da cima a fondo, ho letto tutte le risposte qui e nessuna di queste ha aiutato. Ad essere onesti, ogni risposta dice qualcosa di diverso su come violare questo.Come aggiornare il widget dell'app con la visualizzazione elenco da un'attività
Ora torna alla mia domanda. Voglio aggiornare la vista elenco widget da alcune attività e ho creato WidgetProvider#sendUpdateBroadcastToAllWidgets()
per questo scopo che chiamo dall'attività.
Alla fine chiama lo onUpdate()
in modo che la trasmissione venga ricevuta correttamente. Ma i punti di vista non sono aggiornati.
Ho anche provato a chiamare AppWidgetManager#notifyAppWidgetViewDataChanged()
e aggiornato i dati in WidgetFactory#onDataSetChanged()
ma il metodo non è mai stato chiamato.
Quindi immagino che tutto questo non funzioni perché il factory delle viste remote è memorizzato nella cache ma non so come superarlo in modo affidabile. qualche idea?
E per quanto riguarda i contesti? Devo sempre fornirne uno, ma non mi interessa molto quale. Importa?
Grazie
PROVIDER
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);
}
}
FABBRICA
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;
}
}
Devo avere un brutto karma o qualcosa del genere. Ho fatto questo prima e non ha funzionato, ma ho provato di nuovo comunque e funziona :) Grazie – user219882
E ancora una cosa, non è sufficiente solo notificare che i dati sono cambiati. Questo da solo non funziona per più istanze di un widget. Devi anche chiamare 'updateWidget()' o in generale il codice che si trova in 'onUpdate()' – user219882
come reinserirai il codice in 'onUpdate()'? – natsumiyu