Коли реєструвати / скасувати реєстрацію приймачів трансляцій, створених під час діяльності?


79

Мені потрібно створити власний приймач трансляції в події onCreate діяльності, і, очевидно, мені потрібно скасувати реєстрацію приймача трансляції в події onDestroy діяльності

Для наочності це фрагмент коду, який я використовую

public class AnActivity extends Activity {
    private ResponseReceiver receiver;

    public class ResponseReceiver extends BroadcastReceiver {
           public static final String ACTION_RESP =
              "mypackagename.intent.action.MESSAGE_PROCESSED";

           @Override
            public void onReceive(Context context, Intent intent) {
// TODO Start a dialogue if message indicates successfully posted to server
            }
    }   

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
        filter.addCategory(Intent.CATEGORY_DEFAULT);
        receiver = new ResponseReceiver();
        registerReceiver(receiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

Я читав, що події onPause / onResume та onStart / onStop для діяльності також повинні реєструвати та скасовувати реєстрацію приймача мовлення.

Я справді хочу зрозуміти, що вважається найкращою практикою для цього і чому.


Це тому, що при onDestroy()виклику більше події не будуть слухатися приймачем.
de_billa_

Відповіді:


91

Вам слід зареєструвати та скасувати реєстрацію приймачів onStart()та onStop().

Єдина причина, за якою діяльність реєструється BroadcastReceiver, - це використовувати події якимось чином для поточної діяльності, щоб інформувати Користувача про подію. Якщо onStop()був викликаний, тоActivity це більше не на першому плані, і тому не може оновити Користувача.

Якщо ви хочете отримувати трансляції подій у фоновому режимі, вам слід розглянути можливість використання послуги, як зазначено тут .

Як каже Костянтин, onDestroy()не гарантується виклик, і ви можете продовжувати отримувати трансляції протягом тривалого часу, коли цей номер Activityуже не працює.


3
Ви пропонуєте мені зареєструватися в onResume ЗАМІСТЬ onCreate чи також? Чи завжди викликається onResume, коли створюється дія?
jamesc

9
Ви повинні зареєструватися в onResume, так, onResume () завжди викликається під час відображуваної активності (це останній метод, що викликається до появи вашої активності ( developer.android.com/reference/android/app/Activity.html ), якщо ви реєструєтесь лише на create () і скасуйте реєстрацію onPause (), тоді наступного разу, коли діяльність буде виведена на передній план, onCreate () більше не буде викликатися, а потім знову не зареєструє одержувач. І так, я маю на увазі ЗАМІСТО, не робіть це на Create ().
SnowyTracks

1
@SnowyTracks: чи можете ви прокоментувати, чому переважно виконувати реєстраційні виклики BroadcastReceiver у onResume / onPause, а не onStart / onStop? Переглядаючи посібник розробника для пов'язаних послуг, я виявив це . Ближче до кінця цього розділу рекомендується виконувати прив'язку / розв'язування служби в onStart / onStop, а не onResume / onPause (з міркувань продуктивності). Цікаво, чи стосується це також BroadcastReceivers? Заздалегідь спасибі.
Янус Вармаркен,

1
@jvmk Погоджено, документ Android каже, що це потрібно робити в onStart та onStop, я думаю, що в 99% випадків це мало що робить, різниця лише в поведінці - це діалогічні дії або використовуються часткові дії на передньому плані. Але я
оновлю

1
Бачу, ви вчора відредагували 2-й абзац ... дякую, що доклали зусиль до більш послідовної відповіді. Але це все ще не пояснює, чому слід використовувати onStart / onStop замість або в поєднанні з onResume / onPause , що було питанням OP. Натомість пояснення 2-го абзацу однаково справедливо щодо onResume / onPause, як і onStart / onStop: після виклику onPause діяльність більше не на передньому плані. Тож ми залишаємось без "чому" для вашої рекомендації.
LarsH

19

Оскільки onDestroy()не гарантовано, що Ви будете викликані, Ви будете використовувати onPause()для скасування реєстрації. Розгляньте життєвий цикл вашого приймача мовлення: чи потрібно, щоб він був активним, лише коли ваша діяльність на першому плані? Потім використовуйте onResume()/onPause()


що, якщо нам все-таки потрібно оновити вміст в активності, навіть якщо активність у фоновому режимі, оскільки користувач може відновити роботу програми, і в такому випадку повинні відображатися оновлені дані?
Усман Рана

9

Документація Android не передбачає єдиного місця для реєстрації / скасування реєстрації приймачів мовлення, але в ньому згадується як onStart()/, так onStop()і onResume()/onPause() як можливості.

Найбільший фактор прийняття цього рішення - коли ваш приймач повинен мати можливість виконувати свою роботу? Це визначить час реєстрації та скасування реєстрації.

  • Чи потрібно приймальнику щось робити щодо трансляції лише тоді, коли діяльність зосереджена? Якщо так, ви можете зареєструвати / скасувати реєстрацію в onPause()/ onReceive(). (Ви також можете використовувати більш тривалий час життя, такий як onStart()/ onStop(), але тоді вам слід перевірити під час прийому, onReceive()чи активність знаходиться у фокусі.)

  • Чи потрібно приймачу робити щось, коли воно видно, навіть якщо воно не має фокусу (наприклад, коли відображається діалогове вікно)? Якщо так, використовуйте onStart()/ onStop()(або довший термін служби, але знову ж таки, приймач onReceive()повинен перевірити, чи видима діяльність).

  • Чи повинен одержувач знати про трансляцію, навіть коли діяльність не видно? Наприклад, чи потрібно пам’ятати, що щось сталося, щоб, коли діяльність стає видимою, вона могла відображати результуючий стан справ? Потім вам потрібно використовувати onCreate()/ onDestroy()для реєстрації / скасування реєстрації. (Зверніть увагу, що існують інші способи реалізації такого роду функціональних можливостей.)

Якщо ви реєструєтесь onStart(), не реєструйте їх onResume()і тому, що це було б зайвим: onResume()ніколи не викликається безonStart() викликавшись першим.

Також майте на увазі, що найкраще тримати onPause () якомога легшим :

Виконання onPause () дуже коротке і не обов'язково надає достатньо часу для виконання операцій збереження. З цієї причини не слід використовувати onPause () для збереження даних програми або користувача, здійснення мережевих дзвінків або виконання транзакцій баз даних; така робота може не завершитися до завершення методу. Натомість вам слід виконувати операції відключення великого навантаження під час onStop ().

Це правда , що onDestroy()це не гарантувало буде називатися , якщо система вбиває ваш процес з метою економії пам'яті. Однак якщо процес буде вбито, процес все одно не буде отримувати трансляції. У такому випадку, чи справді необхідно скасувати реєстрацію приймачів мовлення?


Дякуємо за вашу відповідь на моє запитання, але ваша відповідь заплутана і не є суто точною. Ви кажете, що If you register in onStart(), don't also register them in onPause(), because that would be redundant: onPause() is never called without onStart() being called first.це просто нелогічно та заплутано, особливо коли прийнята відповідь є абсолютно точною.
jamesc

@jamesc: На жаль, я мав на увазі onResume, а не onPause. Ви маєте рацію, це трохи заплутано. Виправлено зараз. Що стосується прийнятої відповіді, я її прокоментував. Я вважаю, що ця відповідь додає значну та релевантну інформацію, яку прийнята не пропонує.
LarsH

5

Android може вбити вашу програму, опускаючи onStop()метод. Найкращий спосіб вирішити цю ситуацію - зареєструватись BroadcastReceiverу onResume()методі та скасувати реєстрацію в onPause().


1
Я теж це роблю. Були проблеми з onStop()також добре
Vygintas B

0

Ви повинні зареєструвати та скасувати реєстрацію трансляції в методах onResume () та onPause ().

якщо ви зареєструєтесь у onStart () та скасуєте реєстрацію в onStop (). цього разу ви отримаєте наступний випуск.

якщо екран вашого пристрою заблокований, час виклику onStop () викликається, а якщо ви розблокуєте цей час, він ніколи не викликається. ось чому ви реєструєтесь і скасовуєте реєстрацію в методах onResume () та onPause ().

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.