EventBus: активность не получает событие, когда приложение находится в фоновом режиме
Я использую EventBus
для связи между Activity
и Service
.
Сегодня у меня проблема, и я не знаю почему.
-
У меня есть Activity
, Fragment
и Service
. Все они работают нормально.
-
В Activity
и Fragment
я registered
до Receive
events
, который доставлен из Service
-
В Activity
и Fragment
, я un-register
их при вызове onDestroy()
.
-
В обычных случаях, когда Services
поставляет events
, Fragment
и Activity
могут получать те events
и работать хорошо.
-
Но когда App
нажата на background
(нажатием кнопки "Домой" или "Питание" ), только Fragment
получает события, которые доставлены из Service
, а Activity
не получает их.
-
Я ничего не делал в onPause()
как Activity
, так и Fragment
.
Вопрос:
Есть ли объяснения? И как я могу сделать событие Activity
принимает событие, подобное Fragment
, когда приложение было нажато на фоне?
Ответы
Ответ 1
Когда пользователь нажимает кнопку "назад/домой", Activity
может быть уничтожен в любое время и, следовательно, вы не сможете получать данные с помощью EventBus. Если вы пытаетесь получить данные, когда Activity
находится в фоновом режиме, это может привести к утечке памяти, и приложение выйдет из строя.
Существуют другие подходы к получению данных в Activity
, когда пользователь возобновляет Activity
.
Вы можете либо пользователь sharedpreferences
, либо локальную базу данных, чтобы сохранить пройденные результаты service
. И когда пользователь перейдет к активности, прочитайте его из sharedpreferences
или базы данных.
Таким образом не будет проблем с утечкой памяти или потерей данных.
Изменить 1:
Всегда рекомендуется отменить регистрацию слушателей в onPause
или onStop
, потому что для этого события не нужны эти события, если он не находится на переднем плане. А поскольку onDestroy()
не гарантируется, что вы вызываете, вы можете продолжать получать трансляции, когда активность больше не открыта.
Ответ 2
Класс Activity предоставляет два метода жизненного цикла: onStop() и onRestart(), когда они не видны (фоновый режим), которые позволяют вам конкретно обрабатывать способы остановки и перезапуска вашей активности. В отличие от приостановленного состояния, которое идентифицирует частичную обструкцию пользовательского интерфейса, остановленное состояние гарантирует, что пользовательский интерфейс больше не отображается, а пользовательский фокус находится в отдельной деятельности (или полностью отдельном приложении).
Чтобы понять этот цикл, взгляните на это изображение, которое показывает поток, когда ваше приложение выходит из режима переднего плана.
![Когда пользователь покидает вашу деятельность]()
В вашем случае вы можете справиться с такой проблемой.
- Предоставить пользователю механизм сохранения постоянных данных приложения с использованием локальной базы данных (Sqlite), sharedPreferences.
- Управляйте своей устойчивостью данных по методу onStop().
-
Когда пользователь обращается к вашему приложению, вам необходимо восстановить данные с помощью метода onRestart().
Вот как это реализовать.
public class Calc extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
@Override
protected void onCreate(Bundle state){
super.onCreate(state);
. . .
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent);
}
@Override
protected void onStop(){
super.onStop();
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
// Commit the edits!
editor.commit();
}
}
Прочтите следующую документацию Сайт разработчика Android
Ответ 3
В EventBus версии 3.0.0 вы можете использовать липкие сообщения.
Таким образом, вы можете и должны отменить регистрацию EventBus на "onStop()", чтобы предотвратить утечку памяти и все еще получать события, когда приложение выходит на передний план.
Опубликовать события следующим образом:
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
Подписка событий с липким флагом, например:
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}
Документация EventBus:
http://greenrobot.org/eventbus/documentation/configuration/sticky-events/
Ответ 4
Трудно догадаться, что вы сделали, что вызывает это поведение, подумайте о предоставлении некоторого кода.
Но очевидно, что у вас есть некоторые недостатки дизайна.
Вы должны отменить регистрацию из любой шины или прослушивателя событий в ваших компонентах ui, таких как "Действия" или "Фрагменты", когда пользователь перейдет из приложения, если вы этого не сделаете, есть хорошая вероятность утечки вашей активности и всех ресурсов, которые она имеет место.
Вы должны хранить любые данные, которые вы получаете или рассчитываете в своей фоновой службе, в файл или базу данных, когда пользователь открывает или снова открывает ваше приложение, вы должны проверить эти данные и действовать на него.
Ответ 5
Вам нужно больше кодов или примеров, чтобы помочь вам. Но попробуйте следующее.
- Расширяются ли ваши действия от базы? и если так, удалите незарегистрированный код события onDestroy eventbus и проверьте.
- В настройках разработчика проверьте, не отключена ли опция "Не сохранять действия".
- Нажатие на кнопку "назад" убьет ваше приложение, если вы не переопределили это событие.