Виджет приложения Android: контент добавлен дважды - PullRequest
2 голосов
/ 20 декабря 2010

Я пишу виджет приложения, который я собираюсь заполнить списком элементов. Я пытаюсь сделать это простым способом, расширяя AppWidgetProvider. Я вижу странное поведение, когда список элементов добавляется в родительский виджет дважды.

Вот код:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    Log.i("MyApp", "onUpdate called");

    DbAdapter dbAdapter = new DbAdapter(context);
    dbAdapter.open();

    final String[] columns = { DbTableCategory.KEY_NAME, DbTableCategory.KEY_CURRENTBAL };
    Cursor cursor = dbAdapter.getDb().query(DbTableCategory.TABLE_NAME, columns, null,
                        null, null, null, null);

    final int n = appWidgetIds.length;
    for (int i = 0; i < n; i++) {

        Log.i("MyApp", "Widget instance " + i);

        final int NUM_ITEMS = 4;

        int id = appWidgetIds[i];
        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

        for (int c = 0; c < NUM_ITEMS; c++) {

            // get item info from db
            if (cursor.moveToPosition(c)) {
                RemoteViews itemView = new RemoteViews(context.getPackageName(), R.layout.widget_item);
                itemView.setTextViewText(R.id.widget_item_name, cursor.getString(0));
                itemView.setTextViewText(R.id.widget_item_amnt, cursor.getString(1));

                Log.i("MyApp", "Adding subview for item " + c);
                rv.addView(R.id.widget_container, itemView);
            }
        }

        appWidgetManager.updateAppWidget(id, rv);
    }

    cursor.close();
    dbAdapter.close();

Я добавляю четыре элемента в список, но на самом деле я вижу восемь элементов в виджете (те же четыре появляются дважды). Исходя из вывода журнала, он говорит мне, что есть два экземпляра виджета (в соответствии с массивом appWidgetIds, и идентификаторы различаются), поэтому внешний цикл выполняется дважды, а внутренний цикл (для каждого элемента) работает в четыре раза, как ожидалось. Я не понимаю этого, так как уверен, что только один раз добавил виджет на домашний экран. Его нет ни на одном из других домашних экранов - я использую стандартную программу запуска HTC Sense.

Даже если я дважды создал экземпляр виджета, я создаю новые RemoteViews для каждого экземпляра виджета. Я просто не понимаю, почему один экземпляр виджета, кажется, получает две партии элементов. Что я не так делаю?

Приложение: когда я запускаю точно такой же код в эмуляторе, он работает просто отлично, сообщается только об одном экземпляре виджета. Это только показывает странное поведение на реальном телефоне (HTC Desire, Froyo).

Редактировать: с тех пор я заметил это в документации для RemoteViews.addView():

В тех случаях, когда потребители RemoteViews могут повторно использовать макеты, используйте removeAllViews (int), чтобы очистить все существующие дочерние элементы.

Может быть, тот же экземпляр RemoteViews возвращается из конструктора RemoteViews(...)? Это объясняет, почему дочерние представления добавляются дважды, но не объясняет, почему, во-первых, существует два экземпляра.

Ответы [ 2 ]

4 голосов
/ 27 декабря 2010

Первая проблема с вашим виджетом, возвращающим два appWidgetIds: у меня были похожие ситуации, когда виджет падал (особенно на экранах конфигурации или до того, как виджет был полностью размещен).Настольное приложение по-прежнему будет содержать информацию об этом, но не будет отображать ее.

Вторая (основная) проблема, вероятно, вызвана перезапуском представлений макета, я предполагаю, что R.id.widget_container не очищен,Поэтому вам, вероятно, следует вызвать:

rv.removeAllViews(R.id.widget_container);

перед циклом for.

Кроме того, я бы предложил получить количество возвращаемых строк из курсора (cursor.getCount()), а не жестко кодироватьэто (NUM_ITEMS = 4 в вашем коде).

0 голосов
/ 21 февраля 2014

Я столкнулся с той же проблемой, решение, которое сработало для меня, заключается в удалении любых внутренних дочерних элементов из widget_container, потому что при вызове rv.removeAllViews(R.id.widget_container); этот контейнер изначально не должен иметь дочерних элементов, чтобы не возникало конфликтов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...