preface

In android for UI system often we will encounter all sorts of problems when drawing the UI but don’t know how to solve, sometimes need to develop a change also custom components, the need to do their own adjustment, or is to implement a custom effects when the ideas are not clear, want to play the most basic part of the UI, To get a thorough understanding of the UI drawing process. So I’m going to take you through the whole UI drawing system.

  • Official account: Xiaoxin Chat Android
  • Making the address

UI overall drawing system ideas and doubts

Train of thought

The Android application starts –>Activity loads and completes its life cycle –>setContentView– > Drawing

Confused:

1. How is the Android program started and how is the Activity life cycle invoked?

2. How does our setContentView load the UI file in Activity onCreate?

3. How is the UI drawn?

The answer:

1.Android application flow

As we all know, our Java program needs to rely on the main method to open, that is, our program entrance (main thread) to enter, but in our daily development process of Android program we did not find the existence of the main method, so android is how to start running?

The ActivityThread class represents the main thread of the Android system. In this class, we see the familiar main method. So now can we think that our Android first calls the main of the current class when opening the app, which is our starting point here

You can see here that the Activity calls a attach() method

The first thing we might want to think about here is what does getService get out of it? When we get inside, we’ll find

In this case, the system’s ActivityManagerService is called and a Binder interface is provided

Binder communication in Android. ActivityManager is actually managed by system services called by the Binder interface. This is why we call activities across processes

Now that we know we can get ActivityManager, we can go back to attach and see what the attachApplication method does (see Figure 2). AttachApplication is used by the ActivityThread to attach the applciationThread and store the activity information in the applciationThread. The apllicationThread class prepares the activity for various states

At this point we need to focus on, what is going on in ApplicationThread? When we open ApplicationThread, we see a bunch of schedle methods whose names tell us that they represent scheduled execution methods that are invoked when some state of the Activity is being executed

We see a scheduleLaunchActivity method that is called when the schedule is loaded. And here we found something very interesting

Here we’ll see an ActivityClientRecord object, which is really our Activity, and each method seems to do something very familiar, SendMessage () is used to send out the currently created Activity

When we get to this point, we’ll see that we end up calling Handler’s message communication mechanism. In other words, we can conclude here that when the Activity state changes, a corresponding message will be sent. And when I receive this, I can see that different handlerXXXActivity methods are called in different states when I send it

We can draw a conclusion that, during the process of Application running, the operation of the Activity and the state change is actually completed by the Handler message mechanism. In the main method, Looper is always training, and when we load the Activity, we call a performLaunchActivity() method. And in the middle of that I see the trace of our onCreate call

In other words, so far we can see how the whole process of loading an Activity is going to work. So the next thing we need to focus on is, what does the setContentView that we wrote in onCreate actually do

2.setContentView

In onCreate we tend to use setContentView to set up our own layout file or view, so how does it do that? By looking at the source code, at this point I found the final location of the PhoneWindow class through a series of clues

This time we can see that he does two things, one is installDecor and the other is inflate. It is not hard to guess that he is parsing the layout file, and the other one is initializing something

I came in and found that he had initialized two things called mDecor and mContentParent

We saw that mDecor is a DecorView and mContentParent is a ViewGroup

Through the translation of the notes, we can actually know exactly what these two are used for

// This is the view in which the window contents are placed. It is either // mDecor itself, Or a child of mDecor where the contents go.(It's either mDecor itself or a subclass of mDecor.) //This is the top-level view of the window, containing the window decor.(** This is the top-level view, containing the window decor**)Copy the code

One represents the top view, and the other holds the contents of the view below it. GenerateLayout = generateLayout = generateLayout = generateLayout = generateLayout = generateLayout = generateLayout = generateLayout This is why we have to go to getWindow. RequestFeature before setContent

And then down here we’re going to see that we’re doing something

The layout file is loading, and a view is generated, but it doesn’t seem to be our own. So we need to find out what he has loaded?

This is where I found an interesting component where I saw a comment like this

//This is an optimized layout for a screen, with the minimum set of features enabled.
Copy the code

This is an optimized layout of the screen with minimal feature set enabled. Through annotation and some data analysis, a comparison result is obtained.

This is a default rendering of the DecorView, and our own layout is rendered to her FrameLayout. So here we can see that installDector is actually initializing the two view containers and loading the R resources and features of the system to produce a basic layout

So let’s go back to the other method that we focused on earlier: mLayOutInflater.inflate (layoutResID, mContentParent); This is a little bit easier to understand.

This comment above we can get a message

[Synchronized] // a new view hierarchy is generated from the specified XML resource.Copy the code

I’m going to give you a picture instead of a code

So here we can understand, setContentView actually does two core things, is to load the environment configuration, and its own layout, so the next thing we need to consider is, how does he draw the interface

3. How is the UI drawn?

In the previous two chapters, we learned about the application’s invocation of the Activity lifecycle and the origin of our view resources. This is what we need to find is where is our drawing starting point?

When the ActivityThread started, I noticed that after loading the handleLaunchActivity method and calling the performLaunchActivity method, I called a handleResumeActivity and here I found the start of the drawing process

As we know from the previous flow, after the onCreate trip is complete, all resources are handed over to WindowManager for custody. Here we hand our VIew to WindowManager, and here we call addView

When we go to addView, we find a code that holds the view, its parameters, and a ViewRoot object in a container, so we can say here, save all related objects:

  • MViews holds a View object, DecorView

  • MRoots saves the ViewrotimPL object associated with the top-level View

  • MParams holds the layout parameters that create the top-level View.

  • The Windows ManagerGlobal class is also responsible for communicating with THE WMS

And at this point, there’s a key line of code root.setView, which is giving ViewRoot both our arguments and our view, so let’s look at what the setView in ViewRoot does

Finally here let me find let me understand the step

The view. AssignParent is set to this, which means that the parent is actually a view wroot

SetLayoutParams () is called in the setContentView, which calls the ViewRoot, and setLayoutParams and preformLayout are found in the ViewRoot calling the requestLayout method

The scheduleTraversals method is called in requestLayout and the scheduleTraversals method is called in doduleTraversal, and finally performTraversals(), And in this I found that the overall drawing process is used in turn

UI drawing goes back and measures the layout, then places the layout, and when all the layout measurements have been placed, draws. Now that we know the overall UI drawing process, we can use this drawing process to manipulate our own custom components.

Three things to watch ❤️

If you think this article is helpful to you, I would like to invite you to help me with three small favors: thumbs up and support. Your “thumbs up and comments” are the motivation for my creation.