Заказ диспетчера очереди сообщений Android UI

Во время работы с сохранением фрагментов в Android для хранения AsyncTask во время изменений конфигурации, которые, как я предполагаю, это лучший подход, некоторые сомнения возникают в моем представлении о порядке вызова очереди сообщений UI.

Пример: Представьте себе этот сценарий:

  • происходит изменение конфигурации, пользователь поворачивает устройство. AsyncTask запущен.
  • Фрагмент onDetach() называется
  • Метод AsyncTask doInBackground() завершается
  • AsyncTask onPostExecute() называется
  • Фрагмент onAttach() называется

Таким образом, очередь сообщений в очереди сообщений UI будет выглядеть следующим образом:

Верхняя очередь очереди → onDetach() | onPostExecute() | onAttach()

Я знаю, что это невозможно, вызов onPostExecute() будет ждать завершения изменения конфигурации, насколько я знаю, но как это работает? Являются ли вызовы из "Действия", "Жизненные циклы" фрагментов выполняются последовательно?

Ответ 1

Невозможно вызвать onPostExecute() между Fragment#onDetach() и Fragment#onAttach() во время изменения конфигурации. Причины этого утверждения трижды:

  • Изменения конфигурации обрабатываются внутри одного сообщения в очереди сообщений основного потока.

  • Как только метод doInBackground() возвращается, AsyncTask рассылает метод onPostExecute(), который вызывается в основном потоке, отправляя сообщение в очередь сообщений основного потока.

  • Сообщение об изменении конфигурации будет содержать код, который будет вызывать методы жизненного цикла Activity и Fragment (например, onDetach() и onAttach()). Сообщение AsyncTask будет содержать код, вызывающий метод onPostExecute(). Поскольку основной поток обрабатывает сообщения в очереди сообщений последовательно, невозможно, чтобы оба сообщения выполнялись одновременно, и поэтому onPostExecute() никогда не может быть вызвано между вызовами onDetach() и onAttach().

Прочтите мой ответ Дугу Стивенсону в этой теме для более подробного объяснения (включая ссылки на исходный код, подтверждающий претензию).