How Android Launches MainActivity
I recently did research on the main () method in Java and how it serves as an entry point for any Java application. It made me think, but what about Android apps? Do they have a basic method? How do they load? What happens behind the scenes before onCreate () is executed? Michael Bailey talked in great detail about how Main Thread works, so this is a quick overview of his talk, plus additional information from the Android Open Source Project (AOSP).
In this article we will consider:
When launching any application, a lot of things happen deep inside at the kernel level, for example, Zygote bootstrap, loading classes in the JVM, and for the JVM, finding the main method static void main (String args []) and calling it. In the case of Android, the JVM finds the main main () method in ActivityThread. Then it calls main (), after which the kernel transfers control to your application. So, we found the entry point - ActivityThread, but before exploring this in detail, let's look at the process roadmap to visualize the whole operation.
There are approximately 15 steps between calling the main () method and onCreate () in our MainActivity, and in this article we will go through them. Figure 1 shows a general application startup diagram showing various interaction classes from above and the corresponding chain of methods. The steps are numbered, and when I refer to them, I will use the following notation Process3 or Process14

Figure 1: Scheme of starting the application in steps from calling main () to onCreate () in MainActivity
The ActivityThread class has a little over 6500 lines. For brevity, I have identified the most important parts for us. Let's take a look at what this class and its underlying main method do to start our Activity.
Figure 2: The main () method in ActivityThread, which serves as an entry point to launch your application.
As you can see in the code: the main () method does three important things:
1. Prepares the main Looper (MainLooper) (Process 2)
2. Configures the Handler (Process 4)
3. Calls the Looper.loop () method in the main thread (MainThread ) (Process 6)
The main Looper is defined by calling Looper.prepareMainLooper () (see line 8 in the code). This marks the current random thread, which does all the work of calling the main () method as the main application thread. This is exactly how it is here that the famous main thread for the application in Android is defined!
Inside the ActivityThread class, there is a private inner class H, yes, that's right, just H, which inherits from the Handler class (see. Figures 4 and 7). On line 12, the H-handler instance is installed as the main Handler of the thread. What is very interesting to know about class H, as you will see later, is that it contains more than 50 state / event definitions that your application can be in, for example, LAUNCH_ACTIVITY, PAUSE_ACTIVITY, BIND_SERVICE, etc.
After assigning the main thread in the same main thread, so that we can perform something in it, the Looper.loop () method is called (see Line 20). This starts the execution of messages in the Loopers message queue. Now the main thread is started and can start processing tasks from the queue.
Note that on line 18, if the code execution goes further than Looper.loop () on line 17 and the application exits the loop, a RuntimeException will be thrown. This suggests that the loop () method ideally never ends prematurely. We will see how it is in the next section.
Figure 3: The code inside the loop () method in the Looper'e class
As we see in the code, the Looper.loop () method has a message queue (line 10) and queue.next () is called inside the loop. The MessageQueue is populated with the Handler we talked about in the previous section (see Process 8). Pay attention to the interesting description of the condition in the for loop - there are no arguments, only two semicolons say that it is an infinite loop. Therefore, Looper ideally never ends if a given message is not null.
So, now we have identified the main thread executed by Looper, we also saw that Handler adds messages to the Looper.loops () loop and processes the messages. Let's see how they together invoke our Activity.
It is important to remember that this endless loop and message processing was performed in the main () method of the ActivityThread class, because it was there that they were called (see lines 12 through 17 in the code). We superficially looked at Loopers, MessageQueues and Handlers to gain insight into the context. So, let's return to the ActivityThread class, in particular, to the inner class H, which we talked about earlier, which acts as the main Handler of the main thread.
So, we have a Looper sending messages to our Handler, let's find out how these messages are processed. This is done inside the class H. This class contains the handleMessage (Message msg) method. Remember that all classes that inherit from Handler must override this method.
Figure 4: Private inner class H and its handleMessage () method
As you can see in the code, on the 8th line there is a switch statement, which determines the processing of the incoming message by its contents.
One of the cases involves starting an activity (line 11), which is interesting is that this method is designed to handle about 50 cases, which vary from resuming, pausing, starting an Activity, binding Services, processing Receivers 's, providing lowMemory or trimMemory warnings when the device memory is full, etc.
In case LAUNCH_ACTIVITY, the handleLaunchActivity () method is called, as shown in line 13, see Process11 in the diagram. This method then calls another method called performLaunchActivity (), which returns an Activity object (see Figure 5, line 7).
Figure 5: The handleLaunchActivity () method in which the Activity is created
The performLaunchActivity () method adds important information to the Activity, such as Instrumentation, Context, Component, as well as Intent; and also sets Application. This method then calls Instrumentation.callActivityOnCreate () (Process 13), which is the last step before calling the onCreate () method in Activity (Process 14-15, see Figure 5 (code), lines 8-10).
Figure 6: The Instrumentation class finally starts an Activity
. At the moment, your Activity is loaded with many useful variables and methods that you can use to create your new amazing Android app! All this thanks to ActivityThread, the clever work of Handler and Looper, and the huge Activity class of 7600 lines of code that allows you to attach fragments, get context and easily manage View's - and much more.
This is how our Activity is created!
The original article is here .
In this article we will consider:
- What happens from clicking on the application icon to launching MainActivity
- We find the main application method and find out how the main thread (aka UI, aka Main Thread) gets its purpose.
- Consider the role Looper & Handler plays in messaging, which ultimately leads to the creation of your Activity.
What happens when the application starts
When launching any application, a lot of things happen deep inside at the kernel level, for example, Zygote bootstrap, loading classes in the JVM, and for the JVM, finding the main method static void main (String args []) and calling it. In the case of Android, the JVM finds the main main () method in ActivityThread. Then it calls main (), after which the kernel transfers control to your application. So, we found the entry point - ActivityThread, but before exploring this in detail, let's look at the process roadmap to visualize the whole operation.
1 Application Launch Scheme
There are approximately 15 steps between calling the main () method and onCreate () in our MainActivity, and in this article we will go through them. Figure 1 shows a general application startup diagram showing various interaction classes from above and the corresponding chain of methods. The steps are numbered, and when I refer to them, I will use the following notation Process3 or Process14

Figure 1: Scheme of starting the application in steps from calling main () to onCreate () in MainActivity
2. Class ActivityThread
The ActivityThread class has a little over 6500 lines. For brevity, I have identified the most important parts for us. Let's take a look at what this class and its underlying main method do to start our Activity.
/**
* Code retrieved from https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ActivityThread.java
* Modifications are indicated in the comments
*/
public static void main(String[] args) {
//Modification - Removed unrelated initializers.
//Android initializes some tracers, event loggers, enviroment initializers, trusted certificates and updates the process' state
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// More logging
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}Figure 2: The main () method in ActivityThread, which serves as an entry point to launch your application.
As you can see in the code: the main () method does three important things:
1. Prepares the main Looper (MainLooper) (Process 2)
2. Configures the Handler (Process 4)
3. Calls the Looper.loop () method in the main thread (MainThread ) (Process 6)
2.1 Preparing the main looper (Process 2-3)
The main Looper is defined by calling Looper.prepareMainLooper () (see line 8 in the code). This marks the current random thread, which does all the work of calling the main () method as the main application thread. This is exactly how it is here that the famous main thread for the application in Android is defined!
2.2 Calling Handler'a (Process 4-5)
Inside the ActivityThread class, there is a private inner class H, yes, that's right, just H, which inherits from the Handler class (see. Figures 4 and 7). On line 12, the H-handler instance is installed as the main Handler of the thread. What is very interesting to know about class H, as you will see later, is that it contains more than 50 state / event definitions that your application can be in, for example, LAUNCH_ACTIVITY, PAUSE_ACTIVITY, BIND_SERVICE, etc.
2.3 Call Looper's loop () method (Process 6–7)
After assigning the main thread in the same main thread, so that we can perform something in it, the Looper.loop () method is called (see Line 20). This starts the execution of messages in the Loopers message queue. Now the main thread is started and can start processing tasks from the queue.
Note that on line 18, if the code execution goes further than Looper.loop () on line 17 and the application exits the loop, a RuntimeException will be thrown. This suggests that the loop () method ideally never ends prematurely. We will see how it is in the next section.
3. Endless loop () in Looper (Process 7,8,9)
/**
* AOSP
* Looper class
*/
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
//code removed
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
}
}Figure 3: The code inside the loop () method in the Looper'e class
As we see in the code, the Looper.loop () method has a message queue (line 10) and queue.next () is called inside the loop. The MessageQueue is populated with the Handler we talked about in the previous section (see Process 8). Pay attention to the interesting description of the condition in the for loop - there are no arguments, only two semicolons say that it is an infinite loop. Therefore, Looper ideally never ends if a given message is not null.
So, now we have identified the main thread executed by Looper, we also saw that Handler adds messages to the Looper.loops () loop and processes the messages. Let's see how they together invoke our Activity.
4. Launch MainActivity (Process 10 to 15)
It is important to remember that this endless loop and message processing was performed in the main () method of the ActivityThread class, because it was there that they were called (see lines 12 through 17 in the code). We superficially looked at Loopers, MessageQueues and Handlers to gain insight into the context. So, let's return to the ActivityThread class, in particular, to the inner class H, which we talked about earlier, which acts as the main Handler of the main thread.
So, we have a Looper sending messages to our Handler, let's find out how these messages are processed. This is done inside the class H. This class contains the handleMessage (Message msg) method. Remember that all classes that inherit from Handler must override this method.
/**
* Retrieved from AOSP
* H class embedded in the ActivityThread class
*/
private class H extends Handler {
//Several Application State Identifiers ...
public void handleMessage(Message msg) {
//other code
switch (msg.what) {
case LAUNCH_ACTIVITY: {
//create Activity records
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
...
//handle other cases e.g ResumeActivity, PauseActivity, BindService, UnbindService etc.
}
}
}
}Figure 4: Private inner class H and its handleMessage () method
As you can see in the code, on the 8th line there is a switch statement, which determines the processing of the incoming message by its contents.
One of the cases involves starting an activity (line 11), which is interesting is that this method is designed to handle about 50 cases, which vary from resuming, pausing, starting an Activity, binding Services, processing Receivers 's, providing lowMemory or trimMemory warnings when the device memory is full, etc.
In case LAUNCH_ACTIVITY, the handleLaunchActivity () method is called, as shown in line 13, see Process11 in the diagram. This method then calls another method called performLaunchActivity (), which returns an Activity object (see Figure 5, line 7).
/**
* Retrieved from AOSP.
* ActivityThread class
*/
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//... initialize graphics,do some logging, call GC if need be, etc
Activity a = performLaunchActivity(r, customIntent);
//... handle how to resume an existing activity
}Figure 5: The handleLaunchActivity () method in which the Activity is created
The performLaunchActivity () method adds important information to the Activity, such as Instrumentation, Context, Component, as well as Intent; and also sets Application. This method then calls Instrumentation.callActivityOnCreate () (Process 13), which is the last step before calling the onCreate () method in Activity (Process 14-15, see Figure 5 (code), lines 8-10).
/**
* @Retrieved from AOSP
* Instrumentation class
*/
public void callActivityOnCreate(Activity activity, Bundle icicle) {
// Заметьте что Activity уже создана в prepareLaunchActivity().
// все что нужно жто вызвать onCreate()
prePerformCreate(activity); // подготовка Activity
activity.performCreate(icicle); // вызов onCreate()
postPerformCreate(activity);
}Figure 6: The Instrumentation class finally starts an Activity
. At the moment, your Activity is loaded with many useful variables and methods that you can use to create your new amazing Android app! All this thanks to ActivityThread, the clever work of Handler and Looper, and the huge Activity class of 7600 lines of code that allows you to attach fragments, get context and easily manage View's - and much more.
This is how our Activity is created!
The original article is here .