The underlying principle of Windows add view in Android _android

Source: Internet
Author: User
Tags garbage collection

First, window and WindowManager
window is an abstract class, its implementation is Phonewindow, create a window is very simple, only need to create a windowmanager, window specifically implemented in Windowmanagerservice, The interaction of WindowManager and Windowmanagerservice is a process of IPC.
Here is an example with WindowManager:

Mfloatingbutton = new Button (this); 
      Mfloatingbutton.settext ("window"); 
      Mlayoutparams = new Windowmanager.layoutparams ( 
          layoutparams. Wrap_content, layoutparams.wrap_content, 0, 0, 
          PixelFormat. transparent); 
      Mlayoutparams. Flags = Layoutparams.flag_not_touch_modal 
          | Layoutparams. Flag_not_focusable 
          | Layoutparams. flag_show_when_locked; 
      Mlayoutparams. Type = Layoutparams. Type_system_error; 
      Mlayoutparams. Gravity = Gravity. Left | Gravity. Top; 
      Mlayoutparams. x = m; 
      Mlayoutparams. y =; 
      Mfloatingbutton.setontouchlistener (this); 
      Mwindowmanager.addview (Mfloatingbutton, mlayoutparams);  

Flags and type two attributes are important, and some of the properties are described below, first, flags:
Flag_not_touch_modal means that you do not need to get the focus or receive various inputs, and the final event is passed directly to the lower-level window with focus.
Flag_not_focusable: Zone Click events outside this window to pass to the underlying window. The current area is handled by itself, this is generally to set, very important.
flag_show_when_locked: Open to allow window to display in the lock screen interface.
Let's take a look at this parameter of type:
There are three types of Windows: Application window, child window, System window. The application class corresponds to an activity, and the child window cannot exist alone, and it needs to be attached to the parent window, such as a commonly used dialog. System window is a window, such as toast, that you need to declare permissions to create.
Window has the z-ordered attribute, the larger the hierarchy, the more at the top level. Apply window level 1-99, window1000-1999, System 2000-2999. This level corresponds to the WindowManager type parameter. The system level is commonly used with two type_system_overlay or Type_system_error. Like to use Type_system_error, just
Mlayoutparams.type = Layoutparams.type_system_error. Also add permissions <uses-permission andorid:name= "Android.permission.SYSTEM_ALERT_WINDOW"/>.
With a basic understanding of windows, let's look at how the bottom of the window implements the load view.
second, the creation of window
In fact, the creation of the window is similar to the one I wrote a blog layoutinflater source analysis. The window is created in the Attach method created by the activity, through the Policymanager Makenewwindow method. The callback interface of Windows is implemented in the activity, so the activity method is recalled when the window state changes. such as Onattachedtowindow and so on. The real implementation class for Policymanager is policy, look at its code:

Public Window Makenewwindow {return 
    new Phonewindow (context); 
  } 

To this window to create a complete.
The following is an analysis of how view is attached to Windows. Look at the Setcontentview method of activity.

public void Setcontentview (int layoutresid) { 
    GetWindow (). Setcontentview (LAYOUTRESID); 
    Initwindowdecoractionbar (); 
  

Two parts, setting the content and setting the Actionbar. The concrete implementation of window is Phonewindow, look at its setcontent.

 public void Setcontentview (int layoutresid) {//Note:feature_content_transitions May is set in the process of installing the window//decor, while theme attributes and the like are crystalized. 
    Don't check the feature//before this happens. 
    if (mcontentparent = = null) {Installdecor (); 
    else if (!hasfeature (feature_content_transitions)) {mcontentparent.removeallviews (); } if (Hasfeature (feature_content_transitions)) {final Scene newscene = Scene.getsceneforlayout (mcontentpare 
      NT, Layoutresid, GetContext ()); 
    Transitionto (Newscene); 
    else {mlayoutinflater.inflate (layoutresid, mcontentparent); 
    Final Callback cb = Getcallback (); 
    if (CB!= null &&!isdestroyed ()) {cb.oncontentchanged ()); } 
  }  

See it, analyze it again.
This is done in three steps:
1. If there is no decorview, create Decorview in the Generatedecor () in Installdecor. Analyzed it before, this time it is no longer analyzed.
2. Add view to the Mcontentparent in Decorview.
3. Oncontentchanged interface for callback activity.
After that, Decorview was created, but has not yet been formally added to the window. In Activityresumeactivity, the onresume of the activity is invoked first, and the makevisible,makevisible of the activity is actually added to the view, as follows:

void Makevisible () { 
   if (!mwindowadded) { 
     Viewmanager wm = Getwindowmanager (); 
     Wm.addview (Mdecor, GetWindow (). GetAttributes ()); 
     mwindowadded = true; 
   } 
   Mdecor.setvisibility (view.visible); 
 } 

Add view to window by using the AddView method above.
window operation View internal mechanism
1.window of Add
A window corresponds to a view and a viewrootimpl,window and view through Viewrootimpl to establish a connection, it does not exist, the entity is view. It can only be manipulated by WindowManager.
The implementation class for WindowManager is Windowmanagerimpl. It does not directly implement the three major operations, but entrusted to Windowmanagerglobal. The implementation of AddView is divided into the following steps:
1). Check if the parameter is legal.

 if (view = = null) {throw new IllegalArgumentException ("View must not being null"); 
    } if (display = = null) {throw new IllegalArgumentException ("display must not being null"); } if (! ( params instanceof Windowmanager.layoutparams)) {throw new IllegalArgumentException ("params must be WINDOWMANAGER.L 
    Ayoutparams "); 
    Final Windowmanager.layoutparams wparams = (windowmanager.layoutparams) params; 
    if (ParentWindow!= null) {Parentwindow.adjustlayoutparamsforsubwindow (wparams); else {//If there ' s no parent and we ' re running on L or above (or in the/system context), assume we 
      NT Hardware acceleration. 
      Final context = View.getcontext (); If (context!= null && context.getapplicationinfo (). targetsdkversion >= Build.version_codes. 
      Lollipop) {wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } 
    } 

2. Create Viewrootimpl and add view to the list.

root = new Viewrootimpl (View.getcontext (), display); 
 
      View.setlayoutparams (wparams); 
 
      Mviews.add (view); 
      Mroots.add (root); 
      

3. Through Viewrootimpl to update the interface and complete the window add process.
Root.setview (view, Wparams, Panelparentview);
The root of the above is the Viewrootimpl,setview requestlayout () to complete the asynchronous refresh, look at the requestlayout:

public void Requestlayout () { 
    if (!mhandlinglayoutinlayoutrequest) { 
      checkthread (); 
      Mlayoutrequested = true; 
      Scheduletraversals (); 
    } 
   

Next through Windowsession to complete the window add process, Windowsession is a binder object, the real implementation class is Session,window add is an IPC call.

 try { 
          morigwindowtype = Mwindowattributes.type; 
          Mattachinfo.mrecomputeglobalattributes = true; 
          Collectviewattributes (); 
          res = Mwindowsession.addtodisplay (Mwindow, Mseq, Mwindowattributes, 
              gethostvisibility (), Mdisplay.getdisplayid ( ), 
              mattachinfo.mcontentinsets, Mattachinfo.mstableinsets, Minputchannel); 
        catch (RemoteException e) { 
          madded = false; 
          Mview = null; 
          Mattachinfo.mrootview = null; 
          Minputchannel = null; 
          Mfallbackeventhandler.setview (null); 
          Unscheduletraversals (); 
          Setaccessibilityfocus (null, NULL); 
          throw new RuntimeException ("adding window Failed", e); 

The window is added by Windowmanagerservice within the session.

public int addtodisplay (iwindow window, int seq, windowmanager.layoutparams attrs, 
     int viewvisibility, int Displayid , Rect outcontentinsets, Rect outstableinsets, 
     inputchannel outinputchannel) {return 
   Mservice.addwindow (this , Windows, SEQ, Attrs, viewvisibility, Displayid, 
       outcontentinsets, Outstableinsets, Outinputchannel); 
 

Within the Windowmanagerservice, a separate session is reserved for each application.
deletion of 2.window
Look at the Windowmanagerglobal's Removeview:

public void Removeview (View view, Boolean immediate) { 
    if (view = = null) { 
      throw new IllegalArgumentException ("Vie W must not being null "); 
    } 
 
    Synchronized (mlock) { 
      int index = findviewlocked (view, true); 
      View Curview = mroots.get (index). GetView (); 
      Removeviewlocked (index, immediate); 
      if (Curview = = view) {return 
        ; 
      } 
 
      throw new IllegalStateException ("Calling with View" + View 
          + "but the Viewancestor are attached to" + Curview); 
   } 
  

First call findviewlocked to find the index to delete the view, which is the process of building an array traversal. Then call removeviewlocked to do further deletion.

private void removeviewlocked (int index, Boolean immediate) { 
    Viewrootimpl root = Mroots.get (index); 
    View view = Root.getview (); 
 
    if (view!= null) { 
      Inputmethodmanager IMM = Inputmethodmanager.getinstance (); 
      if (IMM!= null) { 
        imm.windowdismissed (mviews.get (index). Getwindowtoken ()); 
      } 
    Boolean deferred = Root.die (immediate); 
    if (view!= null) { 
      view.assignparent (null); 
      if (deferred) { 
        mdyingviews.add (view); 
      } 
    } 
  

The real delete operation is viewrootimpl to complete. WindowManager provides two kinds of removal interfaces, Removeviewimmediate,removeview. They represent asynchronous deletes and synchronous deletes, respectively. The specific deletion operation is done by Viewrootimpl's die.

Boolean Die (Boolean immediate) { 
    //Make sure we did execute immediately if we are in the middle of a traversal or the Damage 
    //done by Dispatchdetachedfromwindow'll cause havoc on return. 
    if (immediate &&!misintraversal) { 
      Dodie (); 
      return false; 
    } 
 
    if (!misdrawing) { 
      destroyhardwarerenderer (); 
    } else { 
      log.e (TAG, "attempting to destroy" the window while Dr awing!\n "+ 
          " window= "+ This +", title= "+ mwindowattributes.gettitle ()); 
    } 
    Mhandler.sendemptymessage (Msg_die); 
    return true; 
  

If it is removeviewimmediate, call Dodie immediately, if it is Removeview, send a message with handler, Viewrootimpl in handler will process the message and invoke Dodie. Focus on the following dodie:

void Dodie () {checkthread (); 
    if (LOCAL_LOGV) log.v (TAG, "DIE in" + This + "of" + msurface); 
      Synchronized (this) {if (mremoved) {return; 
      } mremoved = true; 
      if (madded) {Dispatchdetachedfromwindow (); 
 
        } if (madded &&!mfirst) {destroyhardwarerenderer (); 
          if (Mview!= null) {int viewvisibility = mview.getvisibility (); 
          Boolean viewvisibilitychanged = Mviewvisibility!= viewvisibility; if (mwindowattributeschanged | | viewvisibilitychanged) {//If layout params have been changed, give 
            EM//To the Windows Manager to make sure it has the correct//animation info. try {if (Relayoutwindow (Mwindowattributes, Viewvisibility, false) & Windowmanagerg Lobal. 
            Relayout_res_first_time)!= 0) {mwindowsession.finishdrawing (Mwindow);  The catch (RemoteException e) {}} msurface.release (); 
    } madded = false; 
  } windowmanagerglobal.getinstance (). Doremoveview (this); 
 }

mainly do four things :
1. Garbage collection related work, such as clearing data, callback and so on.
2. Delete Window through session Remove method, finally call Windowmanagerservice's Removewindow

3. Call Dispathdetachedfromwindow, and Ondetachedfromwindow () and ondetachedfromwindowinternal () are called internally. Ondetachedfromwindow is invoked when view is removed, and it is used for some resource reclamation.
4. Refresh data through Doremoveview, delete related data, such as deleting objects in mroot,mdyingviews.

void Doremoveview (Viewrootimpl root) { 
    synchronized (mlock) { 
      final int index = mroots.indexof (root); 
      if (index >= 0) { 
        mroots.remove (index); 
        Mparams.remove (index); 
        Final View view = Mviews.remove (index); 
        Mdyingviews.remove (view); 
      } 
    if (Hardwarerenderer.strimforeground && hardwarerenderer.isavailable ()) { 
      dotrimforeground (); 
    } 
  } 

3. Update window
look at the updateviewlayout in the Windowmanagerglobal.

public void Updateviewlayout (view view, Viewgroup.layoutparams params) { 
    if (view = = null) { 
      throw new Illegalargu Mentexception ("View must not being null"); 
    } 
    if (!) ( params instanceof Windowmanager.layoutparams)) { 
      throw new IllegalArgumentException ("params must be Windowmanager.layoutparams "); 
    } 
 
    Final Windowmanager.layoutparams wparams = (windowmanager.layoutparams) params; 
 
    View.setlayoutparams (wparams); 
 
    Synchronized (mlock) { 
      int index = findviewlocked (view, true); 
      Viewrootimpl root = mroots.get (index); 
      Mparams.remove (index); 
      Mparams.add (index, wparams); 
      Root.setlayoutparams (Wparams, false); 
    } 
   

Update the Viewrootimpl layoutparams through the Viewrootimpl setlayoutparams, then scheduletraversals the view again, including measurement, layout, redraw, In addition, it will update Windows through Windowsession. This process is implemented by Windowmanagerservice. This is similar to the above, it will not repeat, to this window the bottom source analysis of the end.

The above is the entire content of this article, I hope to help you learn.

Related Article

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.