Follow Innost to understand the Android control (Viewroot) system

Source: Internet
Author: User

The role of Android's control system is to encapsulate:
· Measure the display size and position of each UI element (a piece of text, a picture).
· Layout calculations and drawing for each UI element.
· Redraw when the display content needs to change. For efficiency reasons, the redraw area must be kept as small as possible.
· Parses the type of event received by Inputeventreceiver and determines which UI element should respond to this event.
· Handles many of the window state-related callbacks from the WMS.

1. The architecture of the Activity Control system 1.1 The hierarchy of the Activity control system

For an activity:
· It contains a window (the real type is Phonewindow) and an WindowManager (the real type is a Localwindowmanager) object. These two objects will control the display of the entire activity.
· Phonewindow's top view is Decorview, and the view that we set in the OnCreate function through Setcontentview is just part of the Decorview. Decorview is a framelayout type of viewgroup.
· Localwindowmanager uses Windowmanagerimpl as the final processing object (proxy mode), which has a Viewroot object in the Windowmanagerimpl.
· Viewroot implements the Viewparent interface, which has two important member variables, one mview, which points to the decorview of the activity's top UI unit, and another msurface, This surface contains a canvas (canvas). In addition to this, viewroot also interacts across processes through binder systems and windowmanagerservice.
· Viewroot can handle the handler message, and the activity is displayed by Viewroot in its performtraversals function.
· The entire activity of the drawing process is from the msurface lock a canvas, and then handed to Mview to free play drawing talent, finally unlockcanvasandpost release this canvas.

1. WindowManager

The main function of WindowManager is to provide a simple API that allows the user to easily add a control to the system as a window.
WindowManager is actually an interface inherited from Viewmanager, which provides an API for adding/removing windows, updating the window layout, which can be seen as a WMS proxy class on the client. However, the WindowManager interface differs greatly from the WMS interface, and it is almost impossible to see the WMS from the WindowManager. This also shows that WindowManager has done a lot of work to streamline the WMS interface.

1.1 WindowManager Arch

· Viewmanager interface: The most basic interface in the WindowManager system. Viewmanager defines three functions for adding/removing a control, and for updating the layout of a control. Another implementation of the Viewmanager interface is ViewGroup, which is the base class for the container class control, which is used to accommodate a set of controls to its own area, a set of controls called child controls. ViewGroup can lay out a child control in its own area based on its layout parameters (Layoutparams).
You can compare WindowManager with ViewGroup: Imagine WindowManager is a viewgroup, and its area is the entire screen, and each of the Windows is a single view. WindowManager These view to a specific location on the screen by their layout parameters (Layoutparams) with the help of the WMS. The core work of the two is the same, so both WindowManager and viewgroup inherit from Viewmanager.
WindowManager inherits from this interface, which illustrates the consistency of windowmanager and viewgroup in nature.

· WindowManager interface: The WindowManager interface inherits from the Viewmanager interface, and adds two new interfaces according to some peculiarities of the window. Getdefaultdisplay () is used to know which screen the WindowManager instance will add to the window. Removeviewimmediate () requires WindowManager to complete all destruction before the call returns.

· Windowmanagerimpl class: The implementation of the WindowManager interface. It has no practical logic on its own, and the interface defined by WindowManager is done by Windowmanagerglobal. However, it holds two important read-only members that indicate which screen the window will be displayed on, and which window will be used as a child window, as managed by the Windowmanagerimpl instance. As a result, there may be multiple instances of Windowmanagerimpl in a process.

· Windowmanagerglobal class: It does not inherit any of the above interfaces, but it is the ultimate windowmanager of the implementation. It maintains information about all the windows in the current process that have been added to the system. In addition, there is only one instance of Windowmanagerglobal in a process.

1.2 Adding windows through Windowmanagerglobal

Windowmanagerglobal after the layout parameters have been adjusted through the parent window, the newly created Viewrootimpl, controls, and layout parameters are saved in their three arrays, and the control is managed by the new Viewrootimpl, which completes the window's addition.

The code for the

Add window is not complex. The key points are:
• The parent window modifies the layout parameters of the new window. It is possible to modify only Layoutparams.token and Layoutparams.mtitle two properties. The Mtitle property does not need to be mentioned, only for debugging. The token attribute is worth mentioning. Recalling the previous content, each new window must show the appropriate token to the WMS via Layoutparams.token. The token property is modified through the parent window in the AddView () function to reduce the burden on the developer. Developers do not need to care about token should be set why value, just throw layoutparams to a windowmanager, the rest of the matter will not care. The principle of the
parent window to modify the token property is if the new window is of the Type child window (its type is greater than or equal to Layoutparams.first_sub_window and less than or equal to Layoutparams.last_sub_window). The token held by Layoutparams.token is the ID of its parent window (that is, the return value of Iwindow.asbinder (). Otherwise, the Layoutparams.token will be modified to the ID of the activity to which the parent window belongs (that is, the previously described Apptoken), which is important for a new window of type type_application.
From this point, the ParentWindow parameter of AddView () is the true parent window when and only if the new window type is a child window. Such sub-windows have context menus, pop-up menus, cursors, and so on, and in the WMS, the Mattachedwindow that correspond to the windowstate of these windows are the WindowState that ParentWindow corresponds to. However, there are also some windows, such as dialog window, type Type_application, does not belong to child window, but requires Apptoken as its token, For this parentwindow to give his own apptoken to the new window of the Layoutparams.token. At this point, ParentWindow is not the strict parent window.

· Creates a Viewrootimpl object for the new window. As the name implies, Viewrootimpl implements the root of a control tree. It is responsible for direct communication with the WMS, which manages surface, is responsible for triggering the measurement and layout of the control, is responsible for triggering the drawing of the control, and is also the broker of the input event. In short, Viewrootimpl is the power of the entire control system to function, and is undoubtedly the most critical component of this chapter.

· Add controls, layout parameters, and new Viewrootimpl with the same index values to the three corresponding arrays mviews, Mparams, and mroots for subsequent query needs. controls, layout parameters, and Viewrootimpl together make up a window for the client. In other words, a window in a control system is a ternary group of controls, layout parameters, and Viewrootimpl objects.

· Call the Viewrootimpl.setview () function to give the control to Viewrootimpl for hosting. This action will allow Viewrootimpl to add a window to the WMS, get surface, and redraw a series of actions. This step is the root cause of the control being able to display as a window on the screen!

1.3 Updating the layout of the window updateviewlayout ()

Another function defined by Viewmanager is to update the layout of the view. In WindowManager, the layout of the window is updated. When the layout parameters of the window change, such as layoutparams.width from 100 to 200, you need to notify the WMS to adjust the size of the surface and let the window redraw. This work is done in Windowmanagerglobal by the Updateviewlayout () function.

The job of updating the window layout is very simple in windowmanagerglobal, mainly to save the new layout parameters and then call Viewrootimpl.setlayoutparams () to update.

1.4 Deleting a window

What you need to do:

· Removes the element that corresponds to this window from 3 arrays, including controls, layout parameters, and Viewrootimpl.
· Requires Viewrootimpl to remove the corresponding window (Iwindow) from the WMS and release any resources that need to be reclaimed.

Just one thing to note: it is called the Viewrootimpl.die () function to require Viewrootimpl to remove a window from the WMS and free resources. So one can conclude that Viewrootimpl's life begins with Setview () and ends with die ().

2. Viewrootimpl

Viewrootimpl implements the Viewparent interface as the root of the entire control tree, which is the power of the control tree to function properly, and the control's measurement, layout, drawing, and dispatch of input events are triggered by Viewrootimpl. On the other hand, it is the actual implementation of the Windowmanagerglobal work, so it also needs to be responsible for interacting with the WMS to adjust the window's position size and to handle events from the WMS, such as window size changes.

The creation of 2.1 Viewrootimpl and its important members

The creation process of Viewrootimpl is composed of the constructors and the Setview () method two links. Where constructors mainly initialize the members, Setview () is the place to create the window and establish the input event reception mechanism. At the same time, the message that triggered the first "traverse" operation has been sent to the main thread, and after the first "traversal" is completed, Viewrootimpl will complete the first measurement of the control tree, layout, and get the window's surface from the WMS for the first time in the control tree.

· Mhandler, type Viewroothandler, a thread attached to the creation of Viewrootimpl, which is on the main thread, is used to schedule certain operations that must be done by the main thread to be executed in the main thread. The simultaneous existence of Mhandler and mchoreographer seems somewhat repetitive, in fact, they have a clear and distinct division of labor and meaning. Because Mchoreographer has a vsync attribute when processing messages, it is primarily used to handle redrawing-related operations. However, because Mchoreographer needs to wait for VSync vertical synchronization events to trigger the processing of the next message, the timeliness of processing messages is less than Mhandler. The role of Mhandler is to schedule events that occur in other threads to be executed on the main thread. The so-called events that occur in other threads refer to the callbacks that come from the WMS, which are raised by Mwindow that inherit from Iwindow.stub. Because Mwindow is the bn side of a binder object, these callbacks occur in the binder's thread pool. These callbacks affect the re-measurement, layout, and drawing of the control system, so this handler is required to schedule callbacks into the main thread.

Note that the two members of Mhandler and Mthread exist for a single-threaded model. Android UI operations are not thread-safe, and many operations are built on a single-threaded assumption (such as scheduletraversals ()). The single-threaded model is designed to reduce the complexity of the system and reduce the cost of locks.

· Msurface, the type is surface. A surface instance created with the parameterless constructor. Msurface is an empty shell with no content at this point and cannot be applied until the WMS assigns a piece of surface to it through Relayoutwindow ().

· Mwinframe, Mpendingcontentinset, Mpendingvisibleinset, and Mwidth,mheight. These members store information about the layout of the window. Where Mwinframe, Mpendingconentinsets, Mpendingvisibleinsets and windows in the WMS Frame, contentinsets, visibleinsets are kept in sync. This is because the 3 members are not only the outgoing parameters of Relayoutwindow (), but Viewrootimpl immediately update the values of the 3 members when they receive a callback IWindow.Stub.resize () from the WMS. So these 3 members represent the latest state of the window in the WMS.
Unlike the size of the record window in Mwinframe in WMS, Mwidth/mheight records the size of the window in Viewrootimpl, which is the same in most cases. When the window is re-laid in the WMS and the dimensions change, the Mwinframe is first updated by the IWindow.Stub.resize () callback, at which point the mwinframe is different from the mwidth/mheight. At this point Viewrootimpl will know that the control tree needs to be re-laid to accommodate the new window changes. After the layout is complete, the Mwidth/mheight is assigned the width and height saved in the Mwinframe, and the two are reunified again. The reader will see this process when the Performtraversals () method is subsequently analyzed. In addition, similar to Mwidth/mheight, Viewrootimpl also holds the location information of the window Left/top and contentinsets/visibleinsets for the control tree query. However, these four messages were saved in Mattachinfo.

Viewrootimpl Initializes a series of member variables in its constructor, but the creation process is still incomplete. The role of the VIEWROOTIMPL link is fully established only after it has been assigned a control tree for management and a new window has been added to the WMS. Therefore, further analysis of the Viewrootimpl.setview () method is required.

2.2 Control system Heartbeat: Performtraversals ()

Viewrootimpl sends a message through Requestlayout () to the main thread during its creation that triggers a "traverse" operation, which refers to the Performtraversals () method. It is similar in nature to the performlayoutandplacesurfaceslocked () in WMS and is an all-encompassing approach. Various changes received in Viewrootimpl, such as changes in Window properties from the WMS, dimension changes from the control tree, redraw requests, and so on, raise the Call of Performtraversals () and complete processing in it. Callbacks such as Onmeasure (), OnLayout (), and OnDraw () in the view class and its subclasses are also raised directly or indirectly during the execution of the Performtraversals (). And so, again and again the Performtraversals () call drives the control tree to work methodically, and once this method does not execute properly, the entire control tree will be in a zombie state. Therefore, the performtraversals () function is a viewrootimpl heartbeat.

2.2.1 Performtraversals () Stage of work
Many articles tend to divide the work of performtraversals () into three stages of measurement, layout, and plotting. However, innost that this division hides the WMS's position in the process, and does not reflect the expectation of the window size of the control tree, the final determination of the window size by the WMS, and finally the negotiation process of measuring the results of the WMS. This negotiation process fully embodies the role of Viewrootimpl as an intermediary between the WMS and the control tree.

· Predictive volume phase. This is the first stage after entering the Performtraversals () method, which makes the first measurement of a control tree. Measurement results can be obtained by Mview. Getmeasuredwidth ()/height () obtained. In this phase, you will calculate the size required for the control tree to display its contents, which is the desired window size. At this stage, the Onmeasure () method of the view and its subclasses will get the callback in order along the control tree.

· The Layout window stage. Based on the result of the forecast, the Iwindowsession.relayout () method is used to request the resizing of the window to the WMS, which will cause the WMS to re-layout the window and return the layout results to Viewrootimpl.

· Final measurement phase. The result of the forecast amount is the desired window size of the control tree. However, because of the many factors that affect the layout of the windows in the WMS, the WMS does not necessarily layout the window exactly as required by the control tree, and the control tree has to accept the layout results of the WMS because of the strong position of the WMS as a system service. So at this stage, performtraversals () will make the final measurement of the control in the actual size of the window. At this stage, the Onmeasure () method of the view and its subclasses will be recalled in turn along the control tree.

· The layout control tree stage. After the final measurement is complete, the control tree can be laid out. The measurement determines the size of the control, while the layout determines the position of the control. At this stage, the OnLayout () method of the view and its subclasses will be recalled.

· The drawing phase. This is the final stage of Performtraversals (). Once you have determined the position and dimensions of the control, you can draw the control tree. At this stage, the OnDraw () method of the view and its subclasses will be recalled.

2.2.2 Prediction and measurement principle

Candidates for the 2.2.2.1 predictive volume parameters
Prediction is also a complete measurement process, which differs from the final measurement only in the different parameters. The actual measurement work is done in the Onmeasure () method of the view or its subclasses, and its measurement results need to be limited to instructions from its parent control. This instruction is communicated by the two parameters of the Onmeasure () method: Widthspec and Heightspec. They are compound integer variables called Measurespec that instruct the control to measure itself.

The spec_size of the predicted amount is evaluated according to the following principles:
· The first time "traverse", use the maximum size available to the app as a candidate for spec_size.
· This window is a floating window, where one of the layoutparams.width/height is designated as wrap_content, using the maximum size available for the application as a candidate for spec_size.
· In other cases, use the latest window size as a candidate for spec_size.

The compound integer variable of measurespec has two components, the structure

Its 1 to 30 bits give the parent control the recommended dimensions. The effect of the suggested dimensions on the measurement results varies according to the different spec_mode. The value of Spec_mode depends on the setting of the layoutparams.width/height of this control, which can be one of the following three values.
· Measurespec.unspecified (0): Indicates that the control can ignore the value of spec_size while it is being measured. The control can be any size that it expects.
· measurespec.exactly (1): Represents the dimensions that the child control must have for spec_size. This spec_mode is used by the corresponding Measurespec parameter when the control's layoutparams.width/height is a deterministic value, or match_parent.
· Measurespec.at_most (2): Indicates that the child control can be the size it expects, but not greater than spec_size. This spec_mode is used by the corresponding Measurespec parameter when the control's layoutparams.width/height is wrap_content.

2.2.2.2 Measurement Negotiation
Measurehierarchy () is used to measure the entire control tree. The incoming parameters desiredwindowwidth and Desiredwindowheight are carefully selected according to different situations in the preceding code. The control tree can be measured according to these two parameters, but Measurehierarchy () has its own consideration, that is, how to layout the window as elegantly as possible.

This is for a suspended window that sets Layoutparams.width to Wrap_content. As mentioned earlier, when set to Wrap_content, the specified desiredwindowwidth is the maximum width available to the app, so it is possible to produce an ugly layout as shown in the diagram on the left. This situation is more likely to occur in Alertdialog, when Alertdialog needs to display a longer message, because the given width is large enough, it is possible to display the message in one line and make its window full of the entire screen width, which is especially ugly in landscape mode.
The resulting layout results will be much more elegant if the available widths are appropriately constrained to force Alertdialog to display the message in line, as shown in the figure on the right. However, if you do not distinguish the width of the red indiscriminate, when the control tree really needs enough horizontal space, it will cause the content can not be displayed completely, or can not achieve the best display effect. This can happen, for example, when a suspended window wants to display as much of a picture as possible.

So Measurehierarchy () How to solve this question? It takes the approach of negotiating with the control tree by using the desired width limit of measurehierarchy () to attempt to measure the control tree, and then through the measurement results to check whether the control tree can meet its full display content under this restriction. If not, then Measurehierarchy () will make concessions, loosen the width limit, then measure again and check again. If it is still not satisfied, then make concessions again.

Obviously, for non-suspended windows, that is, when Layoutparams.width is set to Match_parent, there is no negotiation process, which is measured directly with the given desiredwindowwidth/height. For the hover window, measurehierarchy () can make two concessions in a row. Thus, in the most unfavourable case, in a "traversal" of Viewrootimpl, the control tree needs to be measured three times, that is, every view.onmeasure () in the control tree is called three times in a row. Therefore, the effect of Onmeasure () method on the performance of OnLayout () is relatively large.

2.2.3 Measurement principle

For a non-viewgroup control, its implementation is relatively simple, as long as the measurespec principle to calculate the required size. For a viewgroup type of control, the situation is much more complicated because it not only has the content that it needs to display (such as the background), its child controls are also what they need to measure. Therefore, it not only needs to calculate the size of its own display content, but also consider the measurement results of its series of child controls. For this it must prepare a measurespec for each child control and invoke the measure () function of each sub-control.

Because the various controls are implemented in a variety of ways, developers can develop new controls on their own, so the measurement algorithms in Onmeasure () will vary. There are some implementations of the onmeasure () algorithm that are not available from the perspective of the Android system:
· When a control is being measured, the control needs to calculate its padding dimensions, because padding is part of its size.
· ViewGroup the margin dimensions of the child controls need to be taken into account when making measurements. Because the margin dimensions of the child controls are part of the parent control's dimensions.
· When ViewGroup prepares measurespec for a child control, Spec_mode should depend on the layoutparams.width/height value of the child control. A value of match_parent or a determined size should be exactly,wrap_content when it should be at_most. As for spec_size, it should be understood as a limitation on the size of the ViewGroup child control, that is, viewgroup the maximum size that is obtained by the child controls allowed by its implementation intent. And you need to deduct the margin size of the child controls.
· Although the purpose of the measurement is to determine the size, it is independent of position. However, the position of the child controls must be considered first when the viewgroup is being measured. Because the location of the child control determines the remaining dimensions available to the child control, it also determines the size of the parent control (when the parent control's layoutparams.width/height is Wrap_content).
· Adding Measured_state_too_small in measurement results requires being realistic. When there is not enough space in one Direction to display its content, you should consider taking advantage of space in another direction, such as wrapping text, because adding this tag can cause the parent control to re-measure it to reduce efficiency.
· When the Measured_state_too_small tag is included in the measurement results of a child control, the parent control should adjust and re-measure the Measurespec to the child control whenever possible. If there is no room for adjustment, the parent control should also add Measured_state_too_small to its own measurement results, allowing its parent control to try to adjust.
· ViewGroup must call the measure () method of the child control when measuring the child control, and cannot call its onmeasure () method directly. The most serious consequence of calling the Onmeasure () method directly is that the pflag_layout_required identity of the child control cannot be added to Mprivateflag, causing the child control to be unable to lay out.

2.2.4 Determine if the window size needs to be changed
The condition that determines whether the window size really needs to be changed looks more complicated, and here is a summary of the necessary conditions first:
· Layoutrequested is true, that is, the Viewrootimpl.requestlayout () method has been called. The Requestlayout () method is also available in view. When the content of the control changes so that it needs to resize, it calls its own requestlayout (), and this method is traced back to the root in the control tree and eventually to Viewrootimp.requestlayout (). This causes a performtraversals () call to be raised. This is a necessary condition because performtraversals () is also likely to be called because the control needs to be redrawn. When a control needs to be redrawn only without re-layout, such as when the background color or foreground color changes, the invalidate () method is used to backtrack to Viewrootimpl, which does not pass through the performtraversals () Triggers a performtraversals () call, but is triggered by scheduletraversals (). In this case, layoutrequested is false, which means that the window size does not need to change.
· Windowsizemaychange is true, as discussed earlier, which means that the WMS has unilaterally changed the window size while the control tree's measurement results differ from this size, or the current window is a suspended window, and the measurement results of its control tree will determine the new size of the window.

The following two conditions satisfy one of the above two conditions:
· The measurement results are different from the current size saved in the Viewrootimpl.
· The measurement results of the suspended window are different from the latest size of the window.

2.3 The relationship between Viewroot and WMS

· Viewroot cross-process communication through the iwindowsession and WMS processes. The iwindowsession is defined in the Iwindowsession.aidl file. This file is processed by the Aidl tool at compile time and will eventually generate code similar to the BN end and BP side of the native binder, which is described later in this article. System private Per-application interface to the window Manager: This means that each app process will establish a iwindowsession session with the WMS. This session is used by app processes to communicate with WMS. Its requestlayout function is described later.

· There is a W type object inside the Viewroot, which is also a binder-based communication class, and W is the bn side of the Iwindow for responding to requests. Iwindow is defined in another Aidl file iwindow.aidl. API back to a client window, the window Manager uses to Informit of interesting things happening: The main idea of this sentence is that Iwindow is the WMS used to do The event notification. Whenever something happens, the WMS will tell it to a iwindow. You can think of Iwindow as a callback function.

2.4 How a keystroke event is distributed in the Viewroot

· The systemserver process where the WMS is located receives a key event.
· The WMS finds the Iwindow object that corresponds to the process that the UI is at the top of the screen, which is a BP-side object.
· Call the Dispatchkey of this Iwindow object. The BN side of the Iwindow object is located in Viewroot, and Viewroot then finds the view that really handles the event based on the internal view's location information, and finally calls the Dispatchkey function to finish the key processing.
In fact, the distribution mechanism of these key events can be compared with Windows UI programming, the key processing process for Windows applications is:
· Each keystroke event is converted into a message that is added by the system to the message queue of the corresponding process. When the message for the process is distributed, the corresponding window is found according to the handle of the message, and the message is processed by the window.

Follow Innost to understand the Android control (Viewroot) system

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.