Зарегистрируйте BroadcastReceiver в виджете (разница в объекте контекста)

Один случай - когда Вы пробуете к коду модульного теста, который использует WeakReference.

25
задан NguyenDat 25 February 2011 в 01:12
поделиться

1 ответ

Несмотря на то, что Дэвид Уэссер дал отличный ответ, я думаю, что есть еще важная информация, которую нужно добавить. Итак, здесь говорится:

В конце концов, Context - это просто ссылка на различные компоненты вашего собственного приложения (такие как ресурсы, информация о пакете и т. Д.) И на внешнюю операционную систему. Таким образом, все различные контексты, которые вы упомянули, являются просто ссылкой на одну и ту же вещь, единственная разница в том, как долго каждая ссылка действительна.

В конкретном случае AppWidgetProvider контекст, который вы получаете для его методов, является тем же контекстом, который предоставляется BroadcastReceiver методом onReceive. На самом деле AppWidgetProvider - это просто необычное имя для обычного BroadcastReceiver , который вызывает определенные методы при получении намерений, связанных с виджетами, например ACTION_APPWIDGET_UPDATE .

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

context.getApplicationContext.registerReceiver(this, intentName);

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

Поэтому, если вам нужно программно добавить фильтры намерений в BroadcastReceiver , вот мое предложение:

1) Создайте другой BroadcastReceiver в классе долгоживущих контекстов , как класс, который расширяет приложение. Давайте назовем это mMainReceiver .

2) Примените фильтр намерений к нему программно, зарегистрируйте и отмените его регистрацию в соответствии с вашими потребностями.

3) Создайте частное намерение, например MY_ACTION_TIME_TICKER , и запустите его из вашего mMainReceiver метода onReceive.

4) В своем манифесте зарегистрируйте фильтр MY_ACTION_TIME_TICKER на своем приемнике AppWidgetProvider.

Таким образом, у вас может быть один BroadcastReceiver, действующий как мост к вашему AppWidgetProvider, и вы можете зарегистрировать и отменить его регистрацию в любое время.

3
ответ дан 28 November 2019 в 21:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: