激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - 理性分析 Window、Activity、DecorView 以及 ViewRoot 之間關系

理性分析 Window、Activity、DecorView 以及 ViewRoot 之間關系

2021-11-08 22:46Android開發編程 Android

ViewRoot并不屬于View樹的一部分。從源碼實現上來看,它既非View的子類,也非View Group,但它實現了ViewParent接口,這讓它可以作為View的名義上的父視圖。

理性分析 Window、Activity、DecorView 以及 ViewRoot 之間關系

前言

Activity和window,DecorView ,viewRoot是什么關系

今天我們就來講解下,這樣你在面試時候,游刃有余;

一、基本概念介紹

1、Activity

  • Activity負責控制生命周期和處理事件;
  • 負責統籌視圖的添加與顯示,以及通過一些回調方法與Window和View進行交互;
  • 一個Activity包含一個Window,真正控制視圖的是Window,Window才是真正代表一個窗口;
  • 統籌視圖的添加與顯示,通過回調與Window和View進行交互;

2、Window

  • Window是視圖的承載者,是一個抽象類;
  • Activity中持有的實際上是Window的子類PhoneWindow;
  • Window通過WindowManager加載了一個DecorView到Window中,并將DecorView交給了ViewRoot;

3、DecorView

  • DecorView的父類是FrameLayout,是Android View樹的根節;
  • 內部包含一個豎直方向的LinearLayout,它有上下三個部分,上面是個ViewStub,延遲加載的視圖(ActionBar,根據Theme設置),中間的是標題欄(根據Theme設置,有的布局沒有),下面的是內容欄。setContentView所設置的布局文件其實就是被加到內容欄之中的;
  1. ViewGroupcontent=(ViewGroup)findViewById(android.R.id.content);
  2. ViewGrouprootView=(ViewGroup)content.getChildAt(0)

4、ViewRoot

  • 控制View的事件處理和邏輯處理;
  • ViewRoot子類是ViewRootImpl類,它是連接WindowManagerService和DecorView的紐帶,View的三大流程(測量(measure),布局(layout),繪制(draw))均通過ViewRoot來完成;
  • ViewRoot并不屬于View樹的一部分。從源碼實現上來看,它既非View的子類,也非View Group,但它實現了ViewParent接口,這讓它可以作為View的名義上的父視圖;
  • RootView繼承了Handler類,可以接收事件并分發;
  • Android的所有觸屏事件、按鍵事件、界面刷新等事件都是通過ViewRoot進行分發的;

理性分析 Window、Activity、DecorView 以及 ViewRoot 之間關系

二、DecorView的創建整個流程詳解

1、attach

Activity的setContentView()開始

  1. publicvoidsetContentView(@LayoutResintlayoutResID){
  2. getWindow().setContentView(layoutResID);
  3. initWindowDecorActionBar();
  4. }

可以看到實際上是交給Window來裝載視圖的;

  1. finalvoidattach(Contextcontext,ActivityThreadaThread,
  2. Instrumentationinstr,IBindertoken,intident,
  3. Applicationapplication,Intentintent,ActivityInfoinfo,
  4. CharSequencetitle,Activityparent,Stringid,
  5. NonConfigurationInstanceslastNonConfigurationInstances,
  6. Configurationconfig,Stringreferrer,IVoiceInteractorvoiceInteractor,
  7. Windowwindow){
  8. ..................................................................
  9. mWindow=newPhoneWindow(this,window);//創建一個Window對象
  10. mWindow.setWindowControllerCallback(this);
  11. mWindow.setCallback(this);//設置回調,向Activity分發點擊或狀態改變等事件
  12. mWindow.setOnWindowDismissedCallback(this);
  13. .................................................................
  14. mWindow.setWindowManager(
  15. (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
  16. mToken,mComponent.flattenToString(),
  17. (info.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED)!=0);//給Window設置WindowManager對象
  18. ....................................................................
  19. }

在Activity的attach方法中生成了PhoneWindow的實例;

有了Window對象,接下來就將DecorView加載到Window中;

2、setContentView

  1. publicvoidsetContentView(intlayoutResID){
  2. if(mContentParent==null){//mContentParent為空,創建一個DecroView
  3. installDecor();
  4. }else{
  5. mContentParent.removeAllViews();//mContentParent不為空,刪除其中的View
  6. }
  7. mLayoutInflater.inflate(layoutResID,mContentParent);//為mContentParent添加子View,即Activity中設置的布局文件
  8. finalCallbackcb=getCallback();
  9. if(cb!=null&&!isDestroyed()){
  10. cb.onContentChanged();//回調通知,內容改變
  11. }
  12. }

mContentParent就是ContentView所對應的的FrameLayout;

Activity的setContentView的流程大致可以總結為:

Activity首先在Attach方法中生成了PhoneWindow的實例;

在setContentView中直接交給Window來裝載視圖,先在PhoneWindow中創建了一個DecroView;

其中創建的過程中可能根據Theme不同,加載不同的布局格式,即Activity中設置的布局;

3、installDecor

  1. privatevoidinstallDecor(){
  2. if(mDecor==null){
  3. mDecor=generateDecor();//生成DecorView
  4. mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
  5. mDecor.setIsRootNamespace(true);
  6. if(!mInvalidatePanelMenuPosted&&mInvalidatePanelMenuFeatures!=0){
  7. mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
  8. }
  9. }
  10. if(mContentParent==null){
  11. mContentParent=generateLayout(mDecor);//為DecorView設置布局格式,并返回mContentParent
  12. ...
  13. }
  14. }
  15. }
  16. protectedDecorViewgenerateDecor(){
  17. returnnewDecorView(getContext(),-1);
  18. }

很簡單,創建了一個DecorView;

再看generateLayout;

4、generateLayout

  1. protectedViewGroupgenerateLayout(DecorViewdecor){
  2. //從主題文件中獲取樣式信息
  3. TypedArraya=getWindowStyle();
  4. ...................
  5. if(a.getBoolean(R.styleable.Window_windowNoTitle,false)){
  6. requestFeature(FEATURE_NO_TITLE);
  7. }elseif(a.getBoolean(R.styleable.Window_windowActionBar,false)){
  8. //Don'tallowanactionbarifthereisnotitle.
  9. requestFeature(FEATURE_ACTION_BAR);
  10. }
  11. ................
  12. //根據主題樣式,加載窗口布局
  13. intlayoutResource;
  14. intfeatures=getLocalFeatures();
  15. //System.out.println("Features:0x"+Integer.toHexString(features));
  16. if((features&(1<
  17. layoutResource=R.layout.screen_swipe_dismiss;
  18. }elseif(...){
  19. ...
  20. }
  21. Viewin=mLayoutInflater.inflate(layoutResource,null);//加載layoutResource
  22. //往DecorView中添加子View,即文章開頭介紹DecorView時提到的布局格式,那只是一個例子,根據主題樣式不同,加載不同的布局。
  23. decor.addView(in,newViewGroup.LayoutParams(MATCH_PARENT,MATCH_PARENT));
  24. mContentRoot=(ViewGroup)in;
  25. ViewGroupcontentParent=(ViewGroup)findViewById(ID_ANDROID_CONTENT);//這里獲取的就是mContentParent
  26. if(contentParent==null){
  27. thrownewRuntimeException("Windowcouldn'tfindcontentcontainerview");
  28. }
  29. if((features&(1<
  30. ProgressBarprogress=getCircularProgressBar(false);
  31. if(progress!=null){
  32. progress.setIndeterminate(true);
  33. }
  34. }
  35. if((features&(1<
  36. registerSwipeCallbacks();
  37. }
  38. //Remainingsetup--ofbackgroundandtitle--thatonlyapplies
  39. //totop-levelwindows.
  40. ...
  41. returncontentParent;
  • 先從主題中獲取樣式,然后根據樣式;
  • 加載對應的布局到DecorView中,然后從中獲取mContentParent;
  • 獲得到之后,可以回到上面的代碼,為mContentParent添加View,即Activity中的布局;

5、DecorView的顯示

將DecorView建立起來,通過setContentView設置的界面,如何在onResume后對用戶可見,需要從ActivityThread說起;

  1. privatevoidhandleLaunchActivity(ActivityClientRecordr,IntentcustomIntent){
  2. //就是在這里調用了Activity.attach(),接著調用了Activity.onCreate()和Activity.onStart()生命周期,
  3. //但是由于只是初始化了mDecor,添加了布局文件,還沒有把
  4. //mDecor添加到負責UI顯示的PhoneWindow中,所以這時候對用戶來說,是不可見的
  5. Activitya=performLaunchActivity(r,customIntent);
  6. ......
  7. if(a!=null){
  8. //這里面執行了Activity.onResume()
  9. handleResumeActivity(r.token,false,r.isForward,
  10. !r.activity.mFinished&&!r.startsNotResumed);
  11. if(!r.activity.mFinished&&r.startsNotResumed){
  12. try{
  13. r.activity.mCalled=false;
  14. //執行Activity.onPause()
  15. mInstrumentation.callActivityOnPause(r.activity);
  16. }
  17. }
  18. }
  19. }

重點看下handleResumeActivity(),在這其中,DecorView將會顯示出來,同時重要的一個角色;ViewRoot也將登場;

6、handleResumeActivity

  1. finalvoidhandleResumeActivity(IBindertoken,booleanclearHide,
  2. booleanisForward,booleanreallyResume){
  3. //這個時候,Activity.onResume()已經調用了,但是現在界面還是不可見的
  4. ActivityClientRecordr=performResumeActivity(token,clearHide);
  5. if(r!=null){
  6. finalActivitya=r.activity;
  7. if(r.window==null&&!a.mFinished&&willBeVisible){
  8. r.window=r.activity.getWindow();
  9. Viewdecor=r.window.getDecorView();
  10. //decor對用戶不可見
  11. decor.setVisibility(View.INVISIBLE);
  12. ViewManagerwm=a.getWindowManager();
  13. WindowManager.LayoutParamsl=r.window.getAttributes();
  14. a.mDecor=decor;
  15. l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  16. if(a.mVisibleFromClient){
  17. a.mWindowAdded=true;
  18. //被添加進WindowManager了,但是這個時候,還是不可見的
  19. wm.addView(decor,l);
  20. }
  21. if(!r.activity.mFinished&&willBeVisible
  22. &&r.activity.mDecor!=null&&!r.hideForNow){
  23. //在這里,執行了重要的操作,使得DecorView可見
  24. if(r.activity.mVisibleFromClient){
  25. r.activity.makeVisible();
  26. }
  27. }
  28. }
  29. }
  30. }

當我們執行了Activity.makeVisible()方法之后,界面才對我們是可見的;

  1. voidmakeVisible(){
  2. if(!mWindowAdded){
  3. ViewManagerwm=getWindowManager();
  4. wm.addView(mDecor,getWindow().getAttributes());//將DecorView添加到WindowManager
  5. mWindowAdded=true;
  6. }
  7. mDecor.setVisibility(View.VISIBLE);//DecorView可見
  8. }
  • 到此DecorView便可見,顯示在屏幕中;
  • 但是在這其中,wm.addView(mDecor, getWindow().getAttributes());
  • 起到了重要的作用,因為其內部創建了一個ViewRootImpl對象,負責繪制顯示各個子View;
  • 具體來看addView()方法,因為WindowManager是個接口,具體是交給WindowManagerImpl來實現的;

7、addView

  1. publicfinalclassWindowManagerImplimplementsWindowManager{
  2. privatefinalWindowManagerGlobalmGlobal=WindowManagerGlobal.getInstance();
  3. ...
  4. @Override
  5. publicvoidaddView(Viewview,ViewGroup.LayoutParamsparams){
  6. mGlobal.addView(view,params,mDisplay,mParentWindow);
  7. }
  8. }
  9. 交給WindowManagerGlobal的addView()方法去實現;
  10. publicvoidaddView(Viewview,ViewGroup.LayoutParamsparams,
  11. Displaydisplay,WindowparentWindow){
  12. finalWindowManager.LayoutParamswparams=(WindowManager.LayoutParams)params;
  13. ......
  14. synchronized(mLock){
  15. ViewRootImplroot;
  16. //實例化一個ViewRootImpl對象
  17. root=newViewRootImpl(view.getContext(),display);
  18. view.setLayoutParams(wparams);
  19. mViews.add(view);
  20. mRoots.add(root);
  21. mParams.add(wparams);
  22. }
  23. ......
  24. try{
  25. //將DecorView交給ViewRootImpl
  26. root.setView(view,wparams,panelParentView);
  27. }catch(RuntimeExceptione){
  28. }
  29. }
  • 看到其中實例化了ViewRootImpl對象,然后調用其setView()方法;
  • 其中setView()方法經過一些列折騰,最終調用了performTraversals()方法,完成繪制,最終界面才顯示出來;

理性分析 Window、Activity、DecorView 以及 ViewRoot 之間關系

總結

  • Activity就像個控制器,不負責視圖部分。Window像個承載器,裝著內部視圖;
  • DecorView就是個頂層視圖,是所有View的最外層布局;
  • ViewRoot像個連接器,負責溝通,通過硬件的感知來通知視圖,進行用戶之間的交互;

原文鏈接:https://mp.weixin.qq.com/s/JJIyRXwaendpsY7_NsbDaQ

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久免费视频3 | 久久久精品视频在线观看 | 日本在线播放一区二区 | 97中文| 欧美性生活久久久 | 黄网站在线免费看 | 国产电影精品久久 | 圆产精品久久久久久久久久久 | 日韩美香港a一级毛片免费 久久精品视频1 | 牛牛视频在线 | 中国产一级毛片 | 国产视频精品在线 | 热re91久久精品国产99热 | 欧美高清第一页 | 久久精品.com | 色人阁在线视频 | 91精品国产91久久久久久丝袜 | 中国av中文字幕 | h视频在线免费观看 | 色天使中文字幕 | 黄色片快播 | 久国久产久精永久网页 | 一级电影免费在线观看 | 草久网| 粉嫩粉嫩一区二区三区在线播放 | 欧美日韩亚洲精品一区二区三区 | av在线官网 | 午夜久久电影 | 国产精品成人久久久久a级 av电影在线免费 | 久草在线综合 | 精品成人av一区二区在线播放 | 91 在线免费观看 | 日夜操天天干 | 成人黄色小视频在线观看 | 欧美精品电影一区 | 精品国产91一区二区三区 | 国产一区二区三区四 | 中文字幕精品一区久久久久 | 国产一级在线观看视频 | 色网站在线免费观看 | 国产在线地址 |