Существует куча различных кейсов, как меняются ЖЦ Activity, вот например некоторые из них:
👉 Старт первой Activity
👉 Запуск новой Activity поверх старой
👉 Переворот Activity
👉 Уничтожение предыдущих Activity из-за нехватки памяти
👉 Запуск Activity другого приложение поверх наших Activity
Прикол в том, что для каждого из этих кейсов используются свои сервисы и свои подходы вычисления когда нужно вызывать методы ЖЦ. Если разбирать каждый такой кейс, получится дипломная работа, да и вам эта информация ничего не даст. В посте мы разберем лишь кейс со стартом первой Activity и общий подход как система в целом дергает методы ЖЦ без разбора того, как она понимает когда нужно дернуть методы.
Когда я первый раз увидел код приложения под Android, я был в недоумении, а где же метод main? Все казалось какой-то магией, мы создаем Activity у которых когда-то будут вызваны методы. На самом деле метод main есть и его довольно легко найти. Он находится в классе
ActivityThread. ActivityThread это основной поток нашего приложения, тот самый поток в котором работает главный Looper. В ActivityThread сокрыто куча всего, всяких настроек и т.д, но нас сейчас интересует лишь старт Activity.В предыдущем посте мы обсудили, как запускается процесс нашего приложения. Вот что происходит далее, в начале запускается статичный метод
main. В этом методе инициализируется главный Looper и после этого дергается метод bindApplication через IPC у ActivityManagerService. Этим мы сообщаем сервису, что вот мы стартанули приложения и нам сейчас нужна помощь с Activity. Далее ActivityManagerService производит свою магию и дергает уже наш метод ActivityThread, т.к при вызове метода bindApplication мы передали объект нашего ActivityTread. После того как
ActivityManagerService дернул наш метод, ActivityThread отправляет сообщение BIND_APPLICATION в очередь Looper и запускает этот самый Looper. На этом моменте выполнение метода main прекращается, т.к запустился бесконечный цикл Looper. Далее Looper главного потока выполняет сообщения BIND_APPLICATION которое просто вызывает еще один метод для настройки и дальше ничего не происходит потому как в Looper главного потока больше нет сообщений.Пока главный поток настраивался,
ActivityManagerService подготавливал первую Activity к запуску. Как именно он это делает: на основе информации полученной из ActivityThread ActivityManagerService знает о том, какую Activity нужно запустить. Однако он не создает саму Activity, у него лишь есть информация о том, что это за Activity и как ее нужно запустить. Затем он создает специальный объект, этот объект транзакция, в котором есть вся информация перечисленная выше. Этот объект отправляется через IPC в главный Looper нашего приложения. Сообщения транзакции представлены в виде специального сообщения. Как вы знаете можно при помощи специальных колбэков в Handler перехватывать нужные нам сообщения. В нашем приложении есть такой объект как
TransactionExecutor, он и перехватывает эти сообщения и затем выполняет. В переданной транзакции есть информация о том, какой метод ЖЦ какой Activity нужно вызвать. Информация эта представлена специальным объектом, который описывает статус ЖЦ Activity. Если говорить конкретно, то там есть специальный класс наследники которого так и называются
OnCreateActivityItem, OnStartActivityItem и т.д. Получив транзакцию TransactionExecutor дергает нужные методы.По сути это все, в системе есть куча различных сервисов, которые знают о наших Activity и решают у какой Activity какой ЖЦ вызывать. И вызывают они методы ЖЦ через транзакции послание через Binder. Часть транзакции приходят из вне, часть же транзакции создает наше же приложение, например когда одна Activity перекрывает другую. Транзакцию с методом onStop создает сам
ActivityThread.