Recently, I did research on the main () method in Java and how it serves as an entry point for any Java application. It made me think, what about Android apps? Do they have a primary method? How are they loaded? What happens behind the scenes before onCreate ()? Michael Bailey
spoke 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 look at:- What happens from clicking on the application icon to launching MainActivity
- Find the main method of the application and find out how the main thread (also known as UI, or Main Thread) gets its purpose.
- Consider the role Looper & Handler plays in the messaging that ultimately leads to the creation of your Activity.
What happens when the application starts
When you run any application, a lot happens deep inside at the kernel level, for example, loading Zygote, loading classes in JVM, and for JVM - finding the main static void main (String args []) method and invoking it. In the case of Android, the JVM finds the main method main () in the ActivityThread. It then 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 entire operation.
1 Scheme launch application
There are approximately 15 steps between the call to main () and onCreate () in our MainActivity, and in this article we will go through them. Figure 1 shows the general scheme of launching the application, showing the different 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 launching the application step by step from calling main () to onCreate () in MainActivity2. ActivityThread class
In the ActivityThread class, there are just over 6500 lines. For brevity, I identified the most important parts for us. Let's take a look at what this class and the main method associated with it do to launch our Activity.
public static void main(String[] args) {
Figure 2: The main () method in ActivityThread, which serves as the entry point for running your application.As you can see in the code: the main () method performs three important things:1. Prepares the main Looper (MainLooper) (Process 2)
2. Configure Handler'a (Process 4)
3. Calling the Looper.loop () method on the main thread (MainThread) (Process 6)
2.1 Preparing the main looper (Process 2–3)
The main Looper is set 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 the famous main thread for an Android application is determined!
2.2 Calling Handler (Process 4-5)
Inside the ActivityThread class there is a private inner class H, yes, yes, that's right, just H, which is inherited from the Handler class (see Fig. 4 and 7). In the 12th line, an instance of the H-handler is set as the main Handler stream. What is very interesting to know about the class H, as you will see later, is that it contains more than 50 state / event definitions in which your application can be located, for example LAUNCH_ACTIVITY, PAUSE_ACTIVITY, BIND_SERVICE, etc.
2.3 Calling Looper’s loop () Method (Process 6–7)
After the main thread is assigned in the same main thread, in order for us to do 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 running and can start processing tasks from the queue.
Please note that in line 18, if the execution of the code goes further than Looper.loop () in line 17 suddenly and the application exits the loop, a RuntimeException exception will be thrown. This suggests that the loop () method ideally never ends prematurely. We will see this in the next section.
3. Infinite loop () in Looper (Process 7,8,9)
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;
Figure 3: Code inside the loop () method in the Looper classAs we see in the code, in the Looper.loop () method there is a message queue (line 10) and queue.next () is called inside the loop. MessageQueue is filled with the Handler-', which 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 here, only two semicolons say that it is an infinite loop. Therefore, a Looper ideally never ends if the given message is not null.
So, now we have defined the main thread executed by the Looper, we also saw that Handler adds messages to the Looper.loops () loop and processes the messages. Let's see how they together cause our Activity.
4. Run MainActivity (Process 10 to 15)
It is important to remember that this infinite loop and message processing were performed in the main () method of the ActivityThread class, because it was there that they were called (see line 12 through 17 in the code). We skimmed the Loopers, MessageQueues, and Handlers to understand the context. So let's go back 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 that sends messages to our Handler, let's find out how these messages are processed. This is done inside the H class. This class contains the handleMessage (Message msg) method. Remember that all classes that inherit from Handler must override this method.
private class H extends Handler {
Figure 4: Private inner class H and its handleMessage () methodAs can be seen in the code, in the 8th line there is a switch statement, in which the processing of the incoming message is determined by its contents.
One of the cases (cases) includes the launch of activity (line 11), what is interesting is that this method is designed to handle about 50 cases, which range from resuming, suspending, starting an Activity, linking Service's, processing Receiver 's, provide lowMemory or trimMemory warnings when the device memory is full, etc.
In the case of LAUNCH_ACTIVITY, the handleLaunchActivity () method is called, as shown in line 13, see Process11 on the diagram. Then this method calls another method called performLaunchActivity (), which returns an Activity object (see Figure 5, line 7).
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
Figure 5: The handleLaunchActivity () method in which the Activity is createdThe performLaunchActivity () method adds important information to the Activity, such as Instrumentation, Context, Component, and Intent; and also sets the 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).
public void callActivityOnCreate(Activity activity, Bundle icicle) {
Figure 6: Instrumentation class finally launches ActivityAt the moment, your Activity is loaded with many useful variables and methods that you can use to create your new amazing Android application! All this thanks to ActivityThread, the clever work of Handler and Looper, and the huge class of 7600 lines of code that allow you to attach fragments, get context and easily manage View's - and a lot more.
That's how our Activity is created!
Original article
here .