In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "the method tutorial of Activity display interface", interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Next let the editor to take you to learn the "Activity display interface method tutorial" bar!
Animation display
In order to facilitate your understanding, let's first show you the relationship between these people in the form of animation:
Source code analysis starts with the birth of love in childhood.
Before the Activity interface was displayed, it was still an Activity that we couldn't see, so I'll give it a nickname-Xiao'ai.
How was little love born? Anyone familiar with the Activity startup process knows that Xiao Ai's creation takes place in performLaunchActivity:
/ / ActivityThread.java
Private Activity performLaunchActivity (ActivityClientRecord r, Intent customIntent) {
/ / create a ContextImpl
ContextImpl appContext = createBaseContextForActivity (r)
Activity activity = null
Try {
Java.lang.ClassLoader cl = appContext.getClassLoader ()
/ / create an Activity
Activity = mInstrumentation.newActivity (
Cl, component.getClassName (), r.intent)
}
Try {
If (activity! = null) {
/ / complete the initialization of some important data of activity
Activity.attach (appContext, this, getInstrumentation (), r.token
R.ident, app, r.intent, r.activityInfo, title, r.parent
R.embeddedID, r.lastNonConfigurationInstances, config
R.referrer, r.voiceInteractor, window, r.configCallback
R.assistToken)
/ / call the onCreate method of activity
If (r.isPersistable ()) {
MInstrumentation.callActivityOnCreate (activity, r.state, r.persistentState)
} else {
MInstrumentation.callActivityOnCreate (activity, r.state)
}
}
}
Return activity
}
In this process, three main things have been done:
Activity is instantiated and the attach method is called for initialization. The onCreate method is called to load the layout from the layout file and prepare for View display. Find a helper for Xiao Ai to interact with View (PhoneWindow)
As we all know, Xiao Ai was busy after she was founded, so she certainly couldn't manage every View himself, so he found a helper to help her interact with View and manage View.
(decoupling of Activity and View)
What is this helper? This is the window Window, that is, the implementation class PhoneWindow.
This process occurs in the attach method:
/ / Activity.java
Final void attach () {
/ / create a PhoneWindow
MWindow = new PhoneWindow (this, window, activityConfigCallback)
MWindow.setCallback (this)
MWindow.setWindowManager (
(WindowManager) context.getSystemService (Context.WINDOW_SERVICE)
MToken, mComponent.flattenToString ()
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED)! = 0)
}
To make it easier to remember, we call this PhoneWindow housekeeper window housekeeper.
Load layout file (DecorView)
With the window housekeeper, you can continue with the onCreate method, the most important of which is the setContentView method in the onCreate method.
Through setContentView, you can load the View in the layout file.
As mentioned earlier, the management of View is left to the window butler, so it is directly called to the setContentView method of PhoneWindow:
/ / Activity.java
Public void setContentView (@ LayoutRes int layoutResID) {
GetWindow () setContentView (layoutResID)
InitWindowDecorActionBar ()
}
Then the work of loading the layout file begins.
But considering one thing, Activity has different themes, and different themes have different layout structures. So we have to set a top-level View as the boss of all View before loading the layout file we set up.
And this top-level View is DecorView, for convenience, I call him the top little brother, referred to as the little brother.
Take a look at how my brother DecorView was created:
/ / PhoneWindow.java
@ Override
Public void setContentView (int layoutResID) {
If (mContentParent = = null) {
InstallDecor ()
}
If (! hasFeature (FEATURE_CONTENT_TRANSITIONS)) {
MLayoutInflater.inflate (layoutResID, mContentParent)
}
}
Private void installDecor () {
If (mDecor = = null) {
MDecor = generateDecor (- 1)
} else {
MDecor.setWindow (this)
}
If (mContentParent = = null) {
MContentParent = generateLayout (mDecor)
}
}
Protected DecorView generateDecor (int featureId) {
Return new DecorView (context, featureId, this, getAttributes ())
}
In this way, the younger brother DecorView was created, and then it was time for the younger brother to work.
As mentioned above, what did little brother DecorView do when he was created?
To set up different layout structures according to different themes, this work takes place in the generateLayout method, which we will not analyze today.
Looks like the little brother's work is done, too?
Wait, wait, wait.
Going back to the setContentView method above, after calling the installDecor method to create the younger brother, I did one more thing:
/ / load xml layout file
MLayoutInflater.inflate (layoutResID, mContentParent)
Public View inflate (@ LayoutRes int resource, @ Nullable ViewGroup root, boolean attachToRoot) {
Final Resources res = getContext () .getResources ()
Final XmlResourceParser parser = res.getLayout (resource)
Try {
Return inflate (parser, root, attachToRoot)
} finally {
Parser.close ()
}
}
And this inflate is the well-known method of loading layout files. Pass in the xml layout file, parse and combine the parent view--mContentParent we passed in, transform it into a complete tree structure, and finally return the top-level View.
At this point, setContentView's work is done.
To put it simply, we created a younger brother DecorView and combined this top-level view with our incoming xml layout file to generate a multi-tier View.
Shows this View (ViewRootImpl)
View is in place, and the structure is settled. The next step is how to display this View structure so that our phones can show the picture?
That's right, it's drawing.
Who is better to do the drawing of View? Recall the current members:
Xiao Ai Activity: big boss, responsible for co-ordinating. Window housekeeper PhoneWindow: responsible for managing each View. DecorView: the top-level View is responsible for the layout of the theme.
It seems that there is no one in charge of View drawing? Drawing is so important that it is necessary to recruit another friend.
ViewRootImpl shining ✨ debut, for convenience, I call him Xiao Wei.
When was Xiao Wei founded?
Let's take a look at the calling process of Activity. After the onCreate call, the onResume method is called, which starts with the handleResumeActivity method.
@ Override
Public void handleResumeActivity () {
/ / onResume
Final ActivityClientRecord r = performResumeActivity (token, finalStateRequest, reason)
/ / addView
If (r.window = = null & &! a.mFinished & & willBeVisible) {
R.window = r.activity.getWindow ()
View decor = r.window.getDecorView ()
ViewManager wm = a.getWindowManager ()
WindowManager.LayoutParams l = r.window.getAttributes ()
Wm.addView (decor, l)
}
This method mainly does two things:
Call the onResume method to call the addView method of WM.
Xiao Wei doesn't seem to be out yet?
Continue to look at the addView method:
/ / WindowManagerGlobal.java
Public void addView () {
Synchronized (mLock) {
Root = new ViewRootImpl (view.getContext (), display)
View.setLayoutParams (wparams)
MViews.add (view)
MRoots.add (root)
MParams.add (wparams)
Try {
Root.setView (view, wparams, panelParentView)
}
}
}
Public ViewRootImpl (Context context, Display display) {
MContext = context
MWindowSession = WindowManagerGlobal.getWindowSession ()
MThread = Thread.currentThread ()
}
Finally, Wei ViewRootImpl has been created, and in this ViewRootImpl, there are two variables worth watching:
MWindowSession . The type is IWindowSession, which is a Binder object for interprocess communication. Its implementation on the server side is Session, which can be used to complete the work related to WMS. MThread . The thread variable is set to the current thread, that is, the thread when ViewRootImpl is instantiated. Generally, when different threads update UI, it will determine whether the current thread and mThread are equal, and if they are different, an exception will be thrown.
Next, call the setView method of ViewRootImpl, which is naturally the way Wei ViewRootImpl does things:
/ / ViewRootImpl.java
Public void setView () {
Synchronized (this) {
/ / draw
RequestLayout ()
/ / call the addWindow method of WMS
Res = mWindowSession.addToDisplay (mWindow, mSeq, mWindowAttributes
GetHostVisibility (), mDisplay.getDisplayId (), mWinFrame
MAttachInfo.mContentInsets, mAttachInfo.mStableInsets
MAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel)
/ / set this (ViewRootImpl) to parent of view (decorView)
View.assignParent (this)
}
}
There are three main functions:
Trigger drawing (including measurement, layout, drawing) / / ViewRootImpl.java
@ Override
Public void requestLayout () {
If (! mHandlingLayoutInLayoutRequest) {
CheckThread ()
MLayoutRequested = true
ScheduleTraversals ()
}
}
-> scheduleTraversals ()
-> performMeasure () performLayout () performDraw ()
-> measure, layout, draw methods
Call the addWindow method of WMS through Binder
The addToDisplay method eventually WMS the addWindow method of the process, assigning Surface to the window, and this Surface is responsible for displaying the final interface and eventually drawing it to the screen.
Set ViewRootImpl to parent of decorView
After this setting, when the sub-view requests to draw (requestLayout), you can finally find the ViewRootImpl through the parent, and then ViewRootImpl will be responsible for all the View drawing. The whole calling process is:
View.requestLayout-> DecorView.requestLayout-> ViewRootImpl.requestLayout
/ / View.java
Public void requestLayout () {
If (mParent! = null & &! mParent.isLayoutRequested ()) {
MParent.requestLayout ()
}
}
Summary
At this point, Activity has finally completed his startup life cycle, the interface has been displayed, and Xiao Ai has become a formed Activity.
In fact, it is not difficult to find that although there are many intermediate roles, each role is indispensable:
Because the View needs to be managed, the PhoneWindow is created
Because different layout structures need to be displayed according to the theme, the root View DecorView is created
Because you need to deal with various events of View, including drawing and event distribution, you create a ViewRootImpl.
Everyone goes his own way and takes orders from Activity.
Exercise
In the past, when I was in class, I always liked to do a few exercises after learning knowledge. Today, I also bring you a few questions to consolidate my knowledge.
What is the relationship among Activity, PhoneWindow, DecorView and ViewRootImpl? PhoneWindow: is the middle layer of interaction between Activity and View, helping Activity manage View. DecorView: is the top View of all View, that is, the parent of all View. ViewRootImpl: used to handle View-related events, such as drawing, event distribution, and also DecorView's parent. What is the timing of the creation of the four? Activity is created in the performLaunchActivity method and is triggered when startActivity. PhoneWindow, also created in the performLaunchActivity method, and more specifically, the attach method of Activity. DecorView, created in setContentView- > PhoneWindow.installDecor. ViewRootImpl, created in the handleResumeActivity method, is finally created through addView. When did the first drawing of View take place?
The first time the drawing occurs in the handleResumeActivity method, the ViewRootImpl is created through the addView method, and its setView method is called.
Finally, the requestLayout method is called to start the process of layout, measurement and drawing.
What is the cause of the crash caused by thread updating UI?
In the trigger drawing method requestLayout, there is a checkThread method:
Void checkThread () {
If (mThread! = Thread.currentThread ()) {
Throw new CalledFromWrongThreadException (
"Only the original thread that created a view hierarchy can touch its views."
}
}
The mThread is compared to the current thread. MThread is assigned when ViewRootImpl is instantiated.
So the reason for the crash is that the thread when view is drawn to the interface (that is, the thread when ViewRootImpl is created) is not the same thread as the thread that makes UI updates.
At this point, I believe that everyone on the "Activity display interface method tutorial" have a deeper understanding, might as well to the actual operation of it! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.