偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

理性分析 Window、Activity、DecorView 以及 ViewRoot 之間關(guān)系

系統(tǒng) Windows
ViewRoot并不屬于View樹的一部分。從源碼實(shí)現(xiàn)上來看,它既非View的子類,也非View Group,但它實(shí)現(xiàn)了ViewParent接口,這讓它可以作為View的名義上的父視圖。

[[433927]]

文末本文轉(zhuǎn)載自微信公眾號(hào)「 Android開發(fā)編程」,作者 Android開發(fā)編程。轉(zhuǎn)載本文請聯(lián)系 Android開發(fā)編程公眾號(hào)。

前言

Activity和window,DecorView ,viewRoot是什么關(guān)系

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

一、基本概念介紹

1、Activity

  • Activity負(fù)責(zé)控制生命周期和處理事件;
  • 負(fù)責(zé)統(tǒng)籌視圖的添加與顯示,以及通過一些回調(diào)方法與Window和View進(jìn)行交互;
  • 一個(gè)Activity包含一個(gè)Window,真正控制視圖的是Window,Window才是真正代表一個(gè)窗口;
  • 統(tǒng)籌視圖的添加與顯示,通過回調(diào)與Window和View進(jìn)行交互;

2、Window

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

3、DecorView

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

 4、ViewRoot

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

二、DecorView的創(chuàng)建整個(gè)流程詳解

1、attach

Activity的setContentView()開始

  1. public void setContentView(@LayoutRes int layoutResID) { 
  2. getWindow().setContentView(layoutResID); 
  3. initWindowDecorActionBar(); 

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

  1. final void attach(Context context, ActivityThread aThread, 
  2. Instrumentation instr, IBinder token, int ident, 
  3. Application application, Intent intent, ActivityInfo info, 
  4. CharSequence title, Activity parent, String id, 
  5. NonConfigurationInstances lastNonConfigurationInstances, 
  6. Configuration config, String referrer, IVoiceInteractor voiceInteractor, 
  7. Window window) { 
  8. .................................................................. 
  9.         mWindow = new PhoneWindow(this, window);//創(chuàng)建一個(gè)Window對(duì)象 
  10.         mWindow.setWindowControllerCallback(this); 
  11.         mWindow.setCallback(this);//設(shè)置回調(diào),向Activity分發(fā)點(diǎn)擊或狀態(tài)改變等事件 
  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設(shè)置WindowManager對(duì)象 
  18.         .................................................................... 

 在Activity的attach方法中生成了PhoneWindow的實(shí)例;

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

2、setContentView

  1. public void setContentView(int layoutResID) { 
  2.     if (mContentParent == null) {//mContentParent為空,創(chuàng)建一個(gè)DecroView 
  3.     installDecor(); 
  4.     } else { 
  5.         mContentParent.removeAllViews();//mContentParent不為空,刪除其中的View 
  6.     } 
  7.     mLayoutInflater.inflate(layoutResID, mContentParent);//為mContentParent添加子View,即Activity中設(shè)置的布局文件 
  8.     final Callback cb = getCallback(); 
  9.     if (cb != null && !isDestroyed()) { 
  10.         cb.onContentChanged();//回調(diào)通知,內(nèi)容改變 
  11.     } 

 mContentParent就是ContentView所對(duì)應(yīng)的的FrameLayout;

Activity的setContentView的流程大致可以總結(jié)為:

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

在setContentView中直接交給Window來裝載視圖,先在PhoneWindow中創(chuàng)建了一個(gè)DecroView;

其中創(chuàng)建的過程中可能根據(jù)Theme不同,加載不同的布局格式,即Activity中設(shè)置的布局;

3、installDecor

  1. private void installDecor() { 
  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設(shè)置布局格式,并返回mContentParent 
  12.         ... 
  13.         }  
  14.     } 
  15. protected DecorView generateDecor() { 
  16.     return new DecorView(getContext(), -1); 

 很簡單,創(chuàng)建了一個(gè)DecorView;

再看generateLayout;

4、generateLayout

  1. protected ViewGroup generateLayout(DecorView decor) { 
  2.     // 從主題文件中獲取樣式信息 
  3.     TypedArray a = getWindowStyle(); 
  4.     ................... 
  5.     if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) { 
  6.         requestFeature(FEATURE_NO_TITLE); 
  7.     } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) { 
  8.         // Don't allow an action bar if there is no title. 
  9.         requestFeature(FEATURE_ACTION_BAR); 
  10.     } 
  11.     ................ 
  12.     // 根據(jù)主題樣式,加載窗口布局 
  13.     int layoutResource; 
  14.     int features = getLocalFeatures(); 
  15.     // System.out.println("Features: 0x" + Integer.toHexString(features)); 
  16.     if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) { 
  17.         layoutResource = R.layout.screen_swipe_dismiss; 
  18.     } else if(...){ 
  19.         ... 
  20.     } 
  21.     View in = mLayoutInflater.inflate(layoutResource, null);//加載layoutResource 
  22.     //往DecorView中添加子View,即文章開頭介紹DecorView時(shí)提到的布局格式,那只是一個(gè)例子,根據(jù)主題樣式不同,加載不同的布局。 
  23.     decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));  
  24.     mContentRoot = (ViewGroup) in
  25.     ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);// 這里獲取的就是mContentParent 
  26.     if (contentParent == null) { 
  27.         throw new RuntimeException("Window couldn't find content container view"); 
  28.     } 
  29.     if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) { 
  30.         ProgressBar progress = getCircularProgressBar(false); 
  31.         if (progress != null) { 
  32.             progress.setIndeterminate(true); 
  33.         } 
  34.     } 
  35.     if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) { 
  36.         registerSwipeCallbacks(); 
  37.     } 
  38.     // Remaining setup -- of background and title -- that only applies 
  39.     // to top-level windows. 
  40.     ... 
  41.     return contentParent; 
  •  先從主題中獲取樣式,然后根據(jù)樣式;
  • 加載對(duì)應(yīng)的布局到DecorView中,然后從中獲取mContentParent;
  • 獲得到之后,可以回到上面的代碼,為mContentParent添加View,即Activity中的布局;

5、DecorView的顯示

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

  1. private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { 
  2.     //就是在這里調(diào)用了Activity.attach(),接著調(diào)用了Activity.onCreate()和Activity.onStart()生命周期, 
  3.     //但是由于只是初始化了mDecor,添加了布局文件,還沒有把 
  4.     //mDecor添加到負(fù)責(zé)UI顯示的PhoneWindow中,所以這時(shí)候?qū)τ脩魜碚f,是不可見的 
  5.     Activity a = performLaunchActivity(r, customIntent); 
  6.     ...... 
  7.     if (a != null) { 
  8.     //這里面執(zhí)行了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.                 //執(zhí)行Activity.onPause() 
  15.                 mInstrumentation.callActivityOnPause(r.activity); 
  16.                 } 
  17.         } 
  18.     } 

 重點(diǎn)看下handleResumeActivity(),在這其中,DecorView將會(huì)顯示出來,同時(shí)重要的一個(gè)角色;ViewRoot也將登場;

6、handleResumeActivity

  1. final void handleResumeActivity(IBinder token, boolean clearHide,  
  2.                                 boolean isForward, boolean reallyResume) { 
  3.     //這個(gè)時(shí)候,Activity.onResume()已經(jīng)調(diào)用了,但是現(xiàn)在界面還是不可見的 
  4.     ActivityClientRecord r = performResumeActivity(token, clearHide); 
  5.     if (r != null) { 
  6.         final Activity a = r.activity; 
  7.         if (r.window == null && !a.mFinished && willBeVisible) { 
  8.             r.window = r.activity.getWindow(); 
  9.             View decor = r.window.getDecorView(); 
  10.             //decor對(duì)用戶不可見 
  11.             decor.setVisibility(View.INVISIBLE); 
  12.             ViewManager wm = a.getWindowManager(); 
  13.             WindowManager.LayoutParams l = r.window.getAttributes(); 
  14.             a.mDecor = decor; 
  15.             l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 
  16.             if (a.mVisibleFromClient) { 
  17.                 a.mWindowAdded = true
  18.                 //被添加進(jìn)WindowManager了,但是這個(gè)時(shí)候,還是不可見的 
  19.                 wm.addView(decor, l); 
  20.             } 
  21.             if (!r.activity.mFinished && willBeVisible 
  22.                     && r.activity.mDecor != null && !r.hideForNow) { 
  23.                 //在這里,執(zhí)行了重要的操作,使得DecorView可見 
  24.                 if (r.activity.mVisibleFromClient) { 
  25.                     r.activity.makeVisible(); 
  26.                 } 
  27.             } 
  28.         } 
  29.     } 

 當(dāng)我們執(zhí)行了Activity.makeVisible()方法之后,界面才對(duì)我們是可見的;

  1. void makeVisible() { 
  2.    if (!mWindowAdded) { 
  3.         ViewManager wm = getWindowManager(); 
  4.         wm.addView(mDecor, getWindow().getAttributes());//將DecorView添加到WindowManager 
  5.         mWindowAdded = true
  6.     } 
  7.     mDecor.setVisibility(View.VISIBLE);//DecorView可見 
  •  到此DecorView便可見,顯示在屏幕中;
  • 但是在這其中,wm.addView(mDecor, getWindow().getAttributes());
  • 起到了重要的作用,因?yàn)槠鋬?nèi)部創(chuàng)建了一個(gè)ViewRootImpl對(duì)象,負(fù)責(zé)繪制顯示各個(gè)子View;
  • 具體來看addView()方法,因?yàn)閃indowManager是個(gè)接口,具體是交給WindowManagerImpl來實(shí)現(xiàn)的;

7、addView

  1. public final class WindowManagerImpl implements WindowManager {     
  2.     private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); 
  3.     ... 
  4.     @Override 
  5.     public void addView(View view, ViewGroup.LayoutParams params) { 
  6.         mGlobal.addView(view, params, mDisplay, mParentWindow); 
  7.     } 
  8. 交給WindowManagerGlobal 的addView()方法去實(shí)現(xiàn); 
  9. public void addView(View view, ViewGroup.LayoutParams params, 
  10.                     Display display, Window parentWindow) { 
  11.     final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; 
  12.     ...... 
  13.     synchronized (mLock) { 
  14.         ViewRootImpl root; 
  15.         //實(shí)例化一個(gè)ViewRootImpl對(duì)象 
  16.         root = new ViewRootImpl(view.getContext(), display); 
  17.         view.setLayoutParams(wparams); 
  18.         mViews.add(view); 
  19.         mRoots.add(root); 
  20.         mParams.add(wparams); 
  21.     } 
  22.     ...... 
  23.     try { 
  24.         //將DecorView交給ViewRootImpl 
  25.         root.setView(view, wparams, panelParentView); 
  26.     } catch (RuntimeException e) { 
  27.     } 
  •  看到其中實(shí)例化了ViewRootImpl對(duì)象,然后調(diào)用其setView()方法;
  • 其中setView()方法經(jīng)過一些列折騰,最終調(diào)用了performTraversals()方法,完成繪制,最終界面才顯示出來;

總結(jié)

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

 

責(zé)任編輯:武曉燕 來源: Android開發(fā)編程
相關(guān)推薦

2009-04-17 22:25:16

多核四核CPU

2017-02-21 12:20:20

Android事件分發(fā)機(jī)制實(shí)例解析

2012-10-31 09:20:45

數(shù)據(jù)中心制冷PUE

2016-12-12 09:58:47

AndroidAndroid Vie

2021-11-04 09:37:31

Android截屏實(shí)現(xiàn)方式監(jiān)聽截屏

2013-11-14 17:02:41

Android多窗口

2010-03-22 09:43:00

無線交換機(jī)

2010-01-11 11:09:10

C++語法

2011-05-19 17:49:08

ActivityAndroid開發(fā)

2024-03-04 11:12:20

大數(shù)據(jù)物聯(lián)網(wǎng)

2021-01-14 12:17:52

大數(shù)據(jù)數(shù)據(jù)分析技術(shù)

2023-03-07 13:28:17

2015-12-09 09:47:50

2009-06-25 14:46:50

JDKJREJVM

2012-05-31 14:54:59

Hadoop大數(shù)據(jù)

2011-08-08 09:51:52

Cocoa 框架

2015-03-09 11:01:43

2010-08-03 16:21:54

FlexFlash

2020-05-12 16:58:05

LinuxUnix技術(shù)

2012-08-06 10:17:24

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)