Android AppWidgetManager метод updateAppWidget не может установить намерения, загрузить данные. И это происходит случайным образом

Мой виджет состоит из двух кнопок и списка отображения данных. В большинстве случаев, когда вызывается метод onUpdate провайдера виджетов, все загружается нормально, и все довольны.

Однако иногда я заметил, что после вызова метода обновления виджет просто полностью не загружает свои данные. Список не пуст, и все кнопки не реагируют. Это как если бы я инициализировал макет в виджет, но ни один из ожидающих намерений или адаптер для списка не были установлены.

Я зарегистрировал все и обнаружил, что это не так. Ожидаемые намерения ARE создаются, как и адаптер списка, каждый раз, включая случайное время, когда он терпит неудачу. Долгое время я думал, что это связано с тем, как данные списка заполняются в адаптер, но, увидев, что он работает каждый раз, в сочетании с тем, что кнопки не работают, также заставляет меня поверить в метод updateAppWidget (ComponentName, RemoteViews) – это ошибка. Тем не менее, нет ошибок, чтобы помочь мне подтвердить это.

Вот код, который запускается в отдельной службе, вызываемой методом onUpdate AppWidgetProvider:

@SuppressWarnings("deprecation") private void updateWidget(int[] ids) { AppWidgetManager widgetManager = AppWidgetManager.getInstance(this); int[] widgetIds = widgetManager.getAppWidgetIds(new ComponentName(this, WidgetReceiver.class)); for (int currentWidgetId : widgetIds) { RemoteViews widget = new RemoteViews(this.getPackageName(), R.layout.widget_layout); Intent intent = new Intent(this, WidgetService.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, currentWidgetId); intent.putExtra("random", randomNumber); randomNumber++; intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); widget.setRemoteAdapter(currentWidgetId, android.R.id.list, intent); Intent clickIntent = new Intent(this, DetailsActivity.class); PendingIntent pending = PendingIntent.getActivity(this, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); widget.setPendingIntentTemplate(android.R.id.list, pending); Intent settingsIntent = new Intent(this, WidgetSettingsActivity.class); settingsIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent settingsPending = PendingIntent.getActivity(this, 0, settingsIntent, PendingIntent.FLAG_UPDATE_CURRENT); widget.setOnClickPendingIntent(R.id.widget_settings, settingsPending); Intent mainIntent = new Intent(this, MainActivity.class); PendingIntent mainPending = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT); widget.setOnClickPendingIntent(R.id.widget_logo, mainPending); ComponentName widgetCompName = new ComponentName(this, WidgetReceiver.class); widgetManager.updateAppWidget(widgetCompName, widget); } } 

Самое неприятное из-за этой ошибки заключается в том, что я не могу ее достоверно воссоздать. Иногда мне удается (un) повезло, и это показывает его уродливую голову, в другие времена (в большинстве случаев) она отлично работает.

Еще одна вещь, которая, как мне показалось, была интересной, – это то, что я видел ту же самую проблему в виджетах Facebook. Из-за NDA я не могу показать экран своего приложения, когда он терпит неудачу, но я могу показать экран идентичной проблемы Facebook:

Ошибка Facebook

Когда виджет Facebook выглядит так, у него есть те же самые проблемы, что и у меня. Нет загруженных данных, все кнопки не реагируют.

Для Facebook и моего виджета последующий интервал обновления обычно устраняет проблему.

Насколько я понимаю, что я не единственный, кто сталкивается с этим, я все равно не хочу выпускать, пока не исправлю это. Кто-нибудь здесь сталкивался с этим, и еще лучше нашел решение или даже причину проблемы? Спасибо за помощь.

EDIT: Что-то интересное. Я провел эксперимент, где я установил интервал обновления на полный день, а не каждые 30 минут. Моя гипотеза заключалась в том, что, возможно, метод обновления не был причиной, это было нечто другое, из-за чего виджет стал пустым и не отвечал.

Разумеется, примерно через 2 часа я проверил свой телефон, и виджет был мертв, несмотря на то, что не был вызван метод обновления. Это заставило бы меня поверить, что что-то другое вызывает эту проблему, а не widgetManager.updateAppWidget(widgetCompName, widget); Как я думал раньше.

Я знаю, что изменение конфигурации может привести к тому, что виджет будет перестроен, и, следовательно, возможно, что он может выйти из строя. Тем не менее, я уже использую метод onConfigurationChanged класса Service, чтобы перезагрузить виджет, если это необходимо. Есть ли другой случай, например изменение конфигурации, которое может заставить виджет уничтожать и воссоздавать себя?

Solutions Collecting From Web of "Android AppWidgetManager метод updateAppWidget не может установить намерения, загрузить данные. И это происходит случайным образом"

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

Поэтому я был прав в моих отредактированных комментариях в исходном вопросе. Это был не метод обновления AppWidgetManager, который вызвал эту проблему, а скорее какой-то другой процесс Android, который вызвал обновление виджета приложения. К сожалению, я не смог изолировать этот триггер, но я нашел решение.

В моем классе RemoteViewsFactory (в основном оболочке, используемой для загрузки набора данных) у меня был блок кода, который выглядел так:

 RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.widget_layout); if(mItems.size() == 0) views.setViewVisibility(R.id.widget_empty, View.VISIBLE); else views.setViewVisibility(R.id.widget_empty, View.GONE); AppWidgetManager manager = AppWidgetManager.getInstance(mContext); ComponentName widgetCompName = new ComponentName(mContext, WidgetReceiver.class); manager.updateAppWidget(widgetCompName, views); 

В принципе, если список пуст, я показал сообщение «Загрузка», которое заняло всю область, в которой находится список. Если список не был пустым, я бы просто спрятал это сообщение.

Так вот что происходит: когда завод был уничтожен (предположительно для целей памяти), сам виджет не был. Таким образом, весь код, который устанавливает намерения для данных и прочее, не запускался. Тем не менее, фабрика была воссоздана, в которой был запущен блок кода, который обновил виджет приложения с новым объектом удаленных представлений. Этот объект с удаленными представлениями не выполнял ни один из методов, которые вы видите в моем методе onUpdate (), который я изначально опубликовал, поэтому все его функции не работали.

Мораль истории: НЕ используйте updateAppWidget в вашем классе RemoteViewsFactory! Теперь это может сработать, если вы запустите все необходимые строки, но я не могу это подтвердить.