java - 如何使用 Activity 的 ListView 更新 App Widget

标签 java android android-appwidget appwidgetprovider

我知道这个问题已经被问过很多次了,但我从头到尾浏览了文档,阅读了这里的所有答案,但都没有帮助。 老实说,每个答案都说明了如何解决这个问题。

现在回到我的问题。我想从某个 Activity 更新小部件 ListView ,为此我创建了 WidgetProvider#sendUpdateBroadcastToAllWidgets(),我从 Activity 中调用它。

它最终会调用 onUpdate() 以便正确接收广播。但是 View 没有刷新。

我还尝试调用 AppWidgetManager#notifyAppWidgetViewDataChanged() 并刷新 WidgetFactory#onDataSetChanged() 中的数据,但该方法从未被调用过。

所以我猜这一切都不起作用,因为远程 View 工厂被缓存了,但我不知道如何可靠地克服这个问题。有什么想法吗?

那么上下文呢?我总是必须提供一个,但我真的不在乎是哪一个。重要吗?

谢谢

供应商

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;
    }
}

最佳答案

我会说 notifyAppWidgetViewDataChanged方法应该适合您。

您必须构建 AppWidgetManager得到 appWidgetIds然后调用notifyAppWidgetViewDataChanged在你的 AppWidgetManager .

伪代码,

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int appWidgetIds[] = appWidgetManager.getAppWidgetIds(
                           new ComponentName(context, WidgetProvider.class));
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listview);

更多可以查看我的回答here其中包含 github 上的演示。

关于java - 如何使用 Activity 的 ListView 更新 App Widget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35957181/

相关文章:

java - 在 unix 重定向之前在 log4j 中捕获 stderr 和 stdout

android - sqlite android 中的波斯语/阿拉伯语搜索给出了错误的结果

Android updateAppWidget 不更新

android - 是否可以在 appwidget 中检测到长按?

android - 如何在没有代码的情况下隐藏 Android 布局 xml 中的部分可见 View ?

java - Android DialogFragment 检索所选选项

Java:正则表达式模式无法识别 HTML 中的空格

java - JSONPARSE 的实现不起作用

android - onReceiveAd 问题,无法识别的类

Android ActionBarSherlock 在 Fragment(不是 FragmentActivity)中显示 ProgressBarIndeterminate