Небольшое изменение в другом моем сообщении
В принципе у меня есть сообщение Handler
в моем Fragment
которая получает кучу сообщений , которые могут привести к диалогам увольняют или показано на рисунке.
Когда приложение переводится в фоновый режим, я получаю сообщение, onPause
но все равно получаю сообщения, как и следовало ожидать. Однако, поскольку я использую фрагменты, я не могу просто закрыть и показать диалоги, так как это приведет к расширению IllegalStateException
.
Я не могу просто отклонить или отменить разрешение на потерю состояния.
Учитывая, что у меня есть, Handler
мне интересно, есть ли рекомендуемый подход к тому, как я должен обрабатывать сообщения в состоянии паузы.
Одно из возможных решений, которое я рассматриваю, - это записывать сообщения, приходящие во время паузы, и воспроизводить их на onResume
. Это несколько неудовлетворительно, и я думаю, что во фреймворке должно быть что-то, чтобы справиться с этим более элегантно.
Ответы:
Хотя операционная система Android, похоже, не имеет механизма, который в достаточной мере решает вашу проблему, я считаю, что этот шаблон действительно обеспечивает относительно простой в реализации обходной путь.
Следующий класс представляет собой оболочку,
android.os.Handler
которая буферизует сообщения, когда действие приостановлено, и воспроизводит их при возобновлении.Убедитесь, что любой имеющийся у вас код, который асинхронно изменяет состояние фрагмента (например, фиксация, отклонение), вызывается только из сообщения в обработчике.
Выведите свой обработчик из
PauseHandler
класса.Всякий раз, когда ваша деятельность получает
onPause()
звонокPauseHandler.pause()
и дляonResume()
звонкаPauseHandler.resume()
.Замените свою реализацию обработчика
handleMessage()
наprocessMessage()
.Обеспечьте простую реализацию,
storeMessage()
которая всегда возвращаетсяtrue
.Ниже приведен простой пример использования этого
PausedHandler
класса.При нажатии кнопки обработчику отправляется задержанное сообщение.
Когда обработчик получает сообщение (в потоке пользовательского интерфейса), он отображает файл
DialogFragment
.Если
PausedHandler
класс не использовался, было бы показано исключение IllegalStateException, если после нажатия кнопки проверки для запуска диалогового окна была нажата кнопка «Домой».Я добавил
storeMessage()
вPausedHandler
класс метод на тот случай, если какие-либо сообщения должны обрабатываться немедленно, даже если действие приостановлено. Если сообщение обрабатывается, должно быть возвращено false, и сообщение будет отклонено.источник
resume
методsendMessage(msg)
технически использует, могут быть другие потоки, помещающие сообщение в очередь прямо перед (или между итерациями цикла), что означает, что сохраненные сообщения могут чередоваться с поступающими новыми сообщениями. Не уверен, что это имеет большое значение. Может быть, использованиеsendMessageAtFrontOfQueue
(и, конечно, обратная итерация) решит эту проблему?Чуть более простая версия отличного PauseHandler от quickdraw -
Он предполагает, что вы всегда хотите хранить автономные сообщения для воспроизведения. И предоставляет Activity в качестве входных данных,
#processMessages
поэтому вам не нужно управлять им в подклассе.источник
resume()
иpause()
, иhandleMessage
synchronized
?Вот несколько другой способ подойти к проблеме выполнения фиксации фрагмента в функции обратного вызова и избежать проблемы IllegalStateException.
Сначала создайте настраиваемый исполняемый интерфейс.
Затем создайте фрагмент для обработки объектов MyRunnable. Если объект MyRunnable был создан после того, как действие было приостановлено, например, если экран повернут или пользователь нажимает кнопку «домой», он помещается в очередь для последующей обработки с новым контекстом. Очередь сохраняется при любых изменениях конфигурации, потому что для экземпляра setRetain установлено значение true. Метод runProtected запускается в потоке пользовательского интерфейса, чтобы избежать состояния гонки с флагом isPaused.
Наконец, фрагмент можно использовать в основном приложении следующим образом:
источник
В своих проектах я использую шаблон проектирования наблюдателя, чтобы решить эту проблему. В Android широковещательные приемники и намерения являются реализацией этого шаблона.
Что я могу сделать , это создать BroadcastReceiver , который я зарегистрировать в / активность фрагмента в onResume и отмены регистрации в / активность фрагмента в OnPause . В BroadcastReceiver методе «s OnReceive я поставил весь код , который должен работать как результат - в BroadcastReceiver - получение Intent (сообщение) в который был послан в ваше приложение в целом. Чтобы повысить избирательность в отношении того, какие типы намерений может принимать ваш фрагмент, вы можете использовать фильтр намерений, как в примере ниже.
Преимущество этого подхода заключается в том, что намерение (сообщение) может быть отправлено отовсюду в вашем приложении (диалоговое окно, открывающееся поверх вашего фрагмента, асинхронная задача, другой фрагмент и т. Д.). Параметры могут даже передаваться как дополнительные функции.
Еще одно преимущество заключается в том, что этот подход совместим с любой версией Android API, поскольку BroadcastReceivers и Intents были представлены на уровне API 1.
Вам не требуется устанавливать какие-либо особые разрешения для файла манифеста вашего приложения, за исключением случаев, когда вы планируете использовать sendStickyBroadcast (где вам нужно добавить BROADCAST_STICKY).
источник