当前位置:网站首页>The story behind the activity display interface: let you clarify the complex relationships of view

The story behind the activity display interface: let you clarify the complex relationships of view

2021-02-23 17:47:20 The woman programmer of the king

current Android interview , Many interviewers like to dig the bottom , This makes us have to know what it is and why it is .

Today, I want to share with you a friend I've been following for a long time in nuggets , He specially wrote an article to explain Activity behind View The complicated relationships of .

Original address :View I'm not sure about the relationship between you and me

I hope it will be helpful to your study and work .

Preface

stay Activity Show View In the process of , There are some important roles that are always confusing , such as PhoneWindow、DecorView、ViewRootImpl.

There are often interview questions to ask , The relationship between the four of them ? The time to create ?View The first time to draw ? Other questions .

So today, , I'll join you from Activity Start up have a look To show View The whole process , What steps will be taken , What is the relationship between the roles .

Animation display

For your convenience , Let's show you the relationship of these people in the form of animation :

The source code parsing

From the birth of love

stay Activity Before the interface is displayed , It's still something we can't see Activity, I give it a nickname —— Little love .

How was little love born ? be familiar with Activity Everyone who starts the process knows , The creation of little love happened in performLaunchActivity in :

//ActivityThread.java
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // establish ContextImpl
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // establish Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        }

        try {
            if (activity != null) {
                // complete activity Initialization of some important data of 
                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 activity Of onCreate Method 
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
            }
        }

        return activity;
    }

In the process , I did three things :

  • Activity Instantiated
  • Called attach Method to initialize
  • call onCreate Method to start loading the layout from the layout file , do View Preparation for display .

Find a place for Xiao AI and View Interactive helpers (PhoneWindow)

You know that , Little love After being created , Busy business , You can't manage everything by yourself View, So he found a helper , Help her and View Interaction , management View.

(Activity and View The decoupling )

What is this helper ? It's the window Window, That is, the implementation class PhoneWindow 了 .

This process happens in attach In the method :

//Activity.java
final void attach() {
		// establish 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);

    }

For the convenience of memory , We're in charge of this PhoneWindow The housekeeper is called Window manager .

Load the layout file (DecorView)

With the window manager , You can go on onCreate The method , stay onCreate The most important of the methods is this setContentView 了 .

adopt setContentView You can load... In the layout file View.

Said before the ,View The relevant management work is handed over to the window housekeeper , So we call it directly to PhoneWindow Of setContentView Method :

	//Activity.java
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

Then we start loading the layout file .

But for one thing ,Activity There are different themes , Different themes have different layouts . So before loading our own layout file , Set up a The best View, As all View Boss .

And this top level View Namely DecorView, For convenience , I call him The youngest brother , abbreviation The younger brother .

Look at my little brother DecorView How was it 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());
    }

this is it , The younger brother DecorView It's created , Then it's time for my little brother to work .

As mentioned above , The younger brother DecorView What was created for ?

Different layout structures should be set according to different themes , This job happened in generateLayout It's in the way , Let's not analyze it today .

It seems that my younger brother's work has also been completed ?

wait , The application's own layout hasn't been loaded yet , Important things haven't started yet .

Back to the top setContentView In the method , Calling installDecor Method to create a little brother , One more thing was done :

	// 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 It's a familiar way to load layout files . Pass in xml Layout file , Analyze and combine the Father view——mContentParent, Turn it into a complete tree structure , And finally back to the top View.

Come here ,setContentView My work is done ,

To put it simply , Is to create The younger brother DecorView, And combined with this top-level view And what we brought in xml Layout file , It creates a multi-layer structure View.

It shows that View(ViewRootImpl)

View With , The structure has also been decided . The next step is how to show this View structure , Let our mobile phone show the picture ?

you 're right , Namely draw .

About View Who is better to hand over the drawing work to ? Remember the present members :

  • Little love Activity: big boss , Be responsible for overall planning .
  • Window manager PhoneWindow: Responsible for the management of all View.
  • The younger brother DecorView: Topmost View, Responsible for displaying the theme layout .

No one seems to be in charge View Drew ? Drawing is so important , Then we need to recruit another friend .

ViewRootImpl The debut , For convenience , I call him Wei .

When was Xiao Wei founded ?

Then look at Activity Call procedure for , stay onCreate After calling , Will call onResume Method , It starts from handleResumeActivity The method says .

    @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 onResume Method
  • call WM Of addView Method .

It seems that Wei hasn't come out yet ?

Continue to look at 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 And it was created , And this ViewRootImpl in , There are two variables to look at :

  • mWindowSession. The type is IWindowSession, It's a Binder object , For interprocess communication . Its implementation on the server side is Session, You can do it through it WMS Related work .
  • mThread. Set the thread variable to the current thread , That's instantiation ViewRootImpl The thread of time . Generally, different threads are updated UI When , Will determine the current thread and mThread Whether it is equal or not , If different , An exception will be thrown .

Next , It's called ViewRootImpl Of setView Method , This method is naturally Xiao Wei ViewRootImpl The way to do things :

//ViewRootImpl.java
    public void setView() {
        synchronized (this) {
        	// draw 
        	requestLayout();

        	// call WMS Of addWindow Method 
        	res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);

        	// Set up this(ViewRootImpl) by view(decorView) Of parent
			view.assignParent(this);
        }
    }

There are three main functions :

  • Trigger draw ( It includes measurement 、 Layout 、 draw )
//ViewRootImpl.java
    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

    ->scheduleTraversals()
    ->performMeasure() performLayout() performDraw()
    ->measure、layout、draw Method 
  • adopt Binder call WMS Of addWindow Method

addToDisplay The method will eventually WMS In the process of addWindow Method , Assign... To the window Surface, And this Surface Is responsible for the display of the final interface , And it's going to end up on the screen .

  • Set up ViewRootImpl by decorView Of parent

After setting this way , Son view When asked to draw (requestLayout), You can go through it all the time parent Finally find ViewRootImpl, Then from ViewRootImpl To take charge of all View The drawing work of . The whole calling process is :

View.requestLayout -> DecorView.requestLayout -> ViewRootImpl.requestLayout

//View.java
    public void requestLayout() {
        if (mParent != null && !mParent.isLayoutRequested()) {
            mParent.requestLayout();
        }
    }

Summary

Here we are ,Activity Finally completed his startup life cycle , The interface is also displayed , Little love has become shaped Activity.

Although there are more middle roles , But every role is indispensable :

Because you need to manage View, Created PhoneWindow; Because you need to display different layout structures according to the theme , Created the root View DecorView; Because it needs to be dealt with View Of various events , Including drawing 、 Event distribution , Created ViewRootImpl.

Everyone is busy , And obey Activity.

exercises

In class before , Always like to do a few exercises after learning knowledge , Today also brings you a few problems , Consolidate your knowledge .

Activity、PhoneWindow、DecorView、ViewRootImpl The relationship between ?

  • PhoneWindow: yes Activity and View The middle layer of interaction , help Activity management View.
  • DecorView: It's all View Top of View, It's all View Of parent.
  • ViewRootImpl: Used for processing View Related events , Like drawing , Event distribution , It's also DecorView Of parent.

The time to create the four ?

  • Activity Founded in performLaunchActivity In the method , stay startActivity Time to trigger .
  • PhoneWindow, Also created in performLaunchActivity In the method , More specifically Activity Of attach Method .
  • DecorView, Founded in setContentView->PhoneWindow.installDecor.
  • ViewRootImpl, Founded in handleResumeActivity In the method , Finally through addView Be created .

View When did your first drawing take place ?

The first drawing took place in handleResumeActivity In the method , adopt addView Method , Created ViewRootImpl, And called its setView Method .

Finally called requestLayout The method begins to lay out 、 measurement 、 Drawn process .

Thread update UI The cause of the crash ?

When the drawing method is triggered requestLayout in , There is one checkThread Method :

    void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }  

Among them the mThread Compared with the current thread . and mThread Is in ViewRootImpl The value is assigned when instantiating .

So the reason for the collapse is view Threads drawn to the interface ( That is to say ViewRootImpl The thread that was created ) And carry on UI The update thread is not the same thread .

Activity、Dialog、PopupWindow、Toast And Window The relationship between

This is an extended question , Simple from Window From the point of view of :

  • Activity. stay Activity Created during the creation process Window, It's the lowest level Window, be called application Window, Level range 1-99.( There's a lot of hierarchy Window It can cover small level Window)

  • Dialog.Dialog The display process and Activity Basically the same , Also created PhoneWindow, initialization DecorView, And will Dialog View to DecorView in , Finally through addView Show it .

But one difference is ,Dialog Of Window It's not an application window , It is child window , Level range 1000-1999, Son Window The display of must be attached to the application window , It will also cover the application level Window. That's why Dialog The context passed in must be Activity Of Context 了 .

  • PopupWindow.PopupWindow The display is different , It didn't create PhoneWindow, It's a direct creation of View(PopupDecorView), And then through WindowManager Of addView The method shows .

Not created PhoneWindow, Is it just with Window It doesn't matter ?

Not at all , In fact, as long as it is called WindowManager Of addView Method , That is to create Window, It depends on whether you have created PhoneWindow irrelevant .View Namely Window Form of expression , It's just PhoneWindow It's the presence of the world that makes Window The image is more three-dimensional .

therefore PopupWindow through Window It shows , And its Window The hierarchy belongs to Son Window, Must be attached to the application window .

  • Toast.Toast and PopupWindow More like , No new building PhoneWindow, Directly through addView Method display View that will do . But it belongs to The system level Window, Level range 2000-2999, So you don't have to be attached to Activity.

Compare the four , You can find , Just want to show View, It will involve WindowManager Of addView Method , It will be used Window The concept , Then it will be displayed and overlaid on the interface in turn according to different layers .

The difference is ,Activity and Dialog The layout is complicated , There will also be elements such as layout themes , So we used it PhoneWindow Do a decoupling , Help them manage View. and PopupWindow and Toast Simple structure , So just create a new one like DecorView Of View, adopt addView Display to the interface .

Reference resources

《Android In order to decrypt 》 View this 12 ask

Last

Android Learning is a long way to go , What we need to learn is not only superficial technology , We have to go down to the bottom , Figure out the following principle , That's the only way , We can improve our competitiveness , In today's highly competitive world .

There's a lot of knowledge of the underlying principles , And I think the more important learning direction and knowledge , On the my GitHub( Click here to see ), Welcome to learn and progress together .

A journey of a thousand miles begins with a single step. , May you and I share .

版权声明
本文为[The woman programmer of the king]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/02/20210223174446203W.html

随机推荐