Android Window創(chuàng)建過(guò)程

先了解下幾個(gè)概念

Window

1.Window是頂級(jí)窗口外觀和行為策略的抽象基類(lèi)。 是被添加到WindowManager的頂級(jí)視圖良狈。
2.它提供了標(biāo)準(zhǔn)的 UI 策略后添,例如背景、標(biāo)題區(qū)域薪丁、默認(rèn)鍵處理等略遇西。
3.目前僅有的實(shí)現(xiàn)類(lèi)是PhoneWindow馅精。
4.View(Activity、Toast粱檀、Dialog)需要依賴(lài)于Window

WindowManager

1.Window的管理者洲敢,或者說(shuō),Window中View的管理者茄蚯,Window所需要展示的內(nèi)容是由View來(lái)承載的
2.它的具體實(shí)現(xiàn)是WindowManagerImpl压彭,用getSystemService(Context.WINDOW_SERVICE)來(lái)獲取
3.繼承ViewManager

WindowManagerImpl在SystemServiceRegistry類(lèi)中創(chuàng)建

static {
  ...
  registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
      @Override
      public WindowManager createService(ContextImpl ctx) {
            return new WindowManagerImpl(ctx);
      }});
   ...

通過(guò)getSystemService(Context.WINDOW_SERVICE)獲取

WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

WindowManagerService

1.系統(tǒng)服務(wù),繼承繼承 IWindowManager.Stub第队,負(fù)責(zé)協(xié)調(diào)Window的層級(jí)哮塞、顯示及事件派發(fā)等
2.WindowManager是本地端的管理者刨秆,負(fù)責(zé)與WindowManagerService進(jìn)行交互凳谦,這是一個(gè)IPC過(guò)程

在SystemServer啟動(dòng)的時(shí)候,會(huì)創(chuàng)建WindowManagerService并注冊(cè)到ServiceManager中:

// 在main()方法中會(huì)調(diào)用startOtherServices()
private void startOtherServices() {
    ...
    wm = WindowManagerService.main(context, inputManager,  mFactoryTestMode !=         
                               FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore);
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    ...
}

WindowManagerGlobal

1.WindowManagerImpl實(shí)際上是將工作委托給了WindowManagerGlobal來(lái)完成
2.WindowManagerGlobal中主要對(duì)View衡未、ViewRootImpl以及LayoutParams進(jìn)行管理

// view
private final ArrayList<View> mViews = new ArrayList<View>();  
// ViewRootImpl
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
// 參數(shù)
private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();
// 即將移除的view
private final ArraySet<View> mDyingViews = new ArraySet<View>();

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
    ...
}

ViewRootImpl

1.ViewRootImpl不是View尸执,它是頂級(jí)View的管理者。
2.每一個(gè)ViewRootImpl 都對(duì)應(yīng)著一個(gè)ViewTree 缓醋,通過(guò)它來(lái)完成View的繪制及顯示過(guò)程如失。
3.Window與View通過(guò)ViewRootImpl建立起聯(lián)系

Window創(chuàng)建過(guò)程

ActivityThread

啟動(dòng)Activity時(shí),ActivityThread會(huì)處理以下幾件事:
1.拿到Activity一些組件信息送粱,然后通過(guò)Instrumentation反射創(chuàng)建Activity
2.調(diào)用Activity的attach來(lái)完成Window的創(chuàng)建等工作褪贵,
3.回調(diào)onCreate生命周期方法。
4.回調(diào)onResume
5.通過(guò)WindowManager.addView添加Window(具體看后面講解)

public final class ActivityThread extends ClientTransactionHandler {
  
  // 保存所有Activity的相關(guān)信息
  final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();

  // Activity啟動(dòng)
  @Override
  private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
      
      ...
      // 創(chuàng)建activity之前進(jìn)行WindowManagerGlobal的初始化
      WindowManagerGlobal.initialize();
  
      // 創(chuàng)建activity 及調(diào)用onCreate
      Activity a = performLaunchActivity(r, customIntent);

  }

  // Activity啟動(dòng), onCreate
  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){

      ActivityInfo aInfo = r.activityInfo;
      // ... 拿到相關(guān)package抗俄、組件等信息

      // 創(chuàng)建上下文對(duì)象脆丁,實(shí)際創(chuàng)建的是ContextImpl對(duì)象
      ContextImpl appContext = createBaseContextForActivity(r);

      // ... 反射來(lái)創(chuàng)建Activity
      Activity activity = ...

      try { 
          // LoadedApk創(chuàng)建Application對(duì)象
          Application app = r.packageInfo.makeApplication(false, mInstrumentation);

          if (activity != null) {   
          
          Window window = null;
          
          // activity 重啟,拿到上一次的Window动雹,并在PhoneWindow復(fù)用之前的DecorView
          if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
              window = r.mPendingRemoveWindow;
              r.mPendingRemoveWindow = null;
              r.mPendingRemoveWindowManager = null;
          }

          // 這里通過(guò)調(diào)用 activity.attach 創(chuàng)建一個(gè)PhoneWindow
          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);

          ...
          
          // 回調(diào)onCreate
          mInstrumentation.callActivityOnCreate(activity, r.state);

          mActivities.put(r.token, r);

      } catch (SuperNotCalledException e) {
       throw e;
      } 
      ...

      return activity;
  }
  
   @Override
   public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
            
       ...
       // onResume
       final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
       if (r == null) {
            return;
       }
       
       if (r.window == null && !a.mFinished && willBeVisible) {
          // 獲取的Window為PhoneWindow
          r.window = r.activity.getWindow(); 
          // 獲取DecorView
          View decor = r.window.getDecorView(); 
          // 設(shè)為不可見(jiàn)
          decor.setVisibility(View.INVISIBLE);
          // 通過(guò)WindowManager添加到窗體
          ViewManager wm = a.getWindowManager();
          WindowManager.LayoutParams l = r.window.getAttributes();
          wm.addView(decor, l);
          ...
       }
       ...
       if (r.activity.mVisibleFromClient) {
          // 會(huì)調(diào)用decor.setVisibility(View.VISIBLE)設(shè)置為可見(jiàn)
          r.activity.makeVisible();
       }
   }

 public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
            String reason) {
        final ActivityClientRecord r = mActivities.get(token);
        ...
        // onResume
        r.activity.performResume(r.startsNotResumed, reason);
        ...
}
  
  // Activity內(nèi)部類(lèi)槽卫,每一個(gè)Activity對(duì)應(yīng)一個(gè)ActivityClientRecord
  // 存儲(chǔ)在mActivities中
  public static final class ActivityClientRecord {
  
       // activity的token
       public IBinder token;
       
       Intent intent;
       
       // onSaveInstance數(shù)據(jù)保存在這里
       Bundle state;
       
       Activity activity;
       
       // activity附加到的Window,handleResumeActivity進(jìn)行賦值
       Window window;
       
       // 保存由于配置更改而導(dǎo)致頁(yè)面銷(xiāo)毀時(shí)的一些狀態(tài)胰蝠,包括ViewModelStore歼培,F(xiàn)ragment等
       Activity.NonConfigurationInstances lastNonConfigurationInstances;
       
       // activity重啟,拿到上一次的Window茸塞,handleLaunchActivity初始化
       Window mPendingRemoveWindow;
       
       // activity重啟躲庄,拿到上一次的WindowManager,handleLaunchActivity初始化
       WindowManager mPendingRemoveWindowManager;
  }

}


// Activity靜態(tài)內(nèi)部類(lèi)钾虐,保存由于配置更改而導(dǎo)致頁(yè)面銷(xiāo)毀時(shí)的一些狀態(tài)
static final class NonConfigurationInstances {
     // 保存ViewModelStore
     Object activity;
     // 保存Fragment
     HashMap<String, Object> children;
     FragmentManagerNonConfig fragments;
     ArrayMap<String, LoaderManager> loaders;
     VoiceInteractor voiceInteractor;
}

// ComponentActivity靜態(tài)內(nèi)部類(lèi)读跷,用于保存ViewModelStore
static final class NonConfigurationInstances {
     Object custom;
     ViewModelStore viewModelStore;
}

Activity

1.完成PhoneWindow的創(chuàng)建
2.通過(guò)setContentView,在PhoneWindow中創(chuàng)建了DecorView(具體看后面)

public class Activity extends ...{

  private Window mWindow;

  private WindowManager mWindowManager;

  final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
            
      // 創(chuàng)建Window(PhoneWindow)禾唁,并傳入重啟前的window
      mWindow = new PhoneWindow(this, window); 
      // 設(shè)置各種Callback
      mWindow.setWindowControllerCallback(this);
      // this即activity效览,存在Window的mCallback中
      mWindow.setCallback(this);  
      ...
     
      // 設(shè)置WindowManager无切,實(shí)際上設(shè)置的是WindowManagerImpl
      mWindow.setWindowManager( 
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
      mWindowManager = mWindow.getWindowManager();
      ...           
      
   }

   public void setContentView(View view, ViewGroup.LayoutParams params) {
         getWindow().setContentView(view, params);
         initWindowDecorActionBar();
   }
}

PhoneWindow

1.創(chuàng)建DecorView
2.將View填充到mContentParent中

public class PhoneWindow extends Window {

  public PhoneWindow(Context context, Window preservedWindow,
            ActivityConfigCallback activityConfigCallback) {
        this(context);
        // 復(fù)用重啟前的View
        if (preservedWindow != null) {
            mDecor = (DecorView) preservedWindow.getDecorView();
            ...
        }
  }

  @Override
  public void setContentView(View view, ViewGroup.LayoutParams params) {
    
     // mContentParent為ID_ANDROID_CONTENT
     if (mContentParent == null) {
        // 創(chuàng)建DecorView
        installDecor(); 
     } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
     }
     ...
    
     // 將Activity.setContentView添加的布局,填充到mContentParent中
     mContentParent.addView(view, params); 
        
     ...
  }

  // 在ActivityThread的handleResumeActivity中會(huì)獲取DecorView添加到WindowManager中
  // 如果沒(méi)調(diào)用setContentView丐枉,當(dāng)調(diào)用getDecorView會(huì)默認(rèn)創(chuàng)建一個(gè)DecorView
  // 所以不管是那種情況都會(huì)調(diào)用導(dǎo)致DecorView的創(chuàng)建哆键,不過(guò)只會(huì)創(chuàng)建一次
  @Override
  public final @NonNull View getDecorView() {
     if (mDecor == null || mForceDecorInstall) {
        installDecor();
     }
     return mDecor;
  }

  // 創(chuàng)建 DecorView
  private void installDecor() {
  
      if (mDecor == null) {
          // 用來(lái)創(chuàng)建DecorView
          mDecor = generateDecor(-1);
          ...
      } else {
          mDecor.setWindow(this);
      }
      if (mContentParent == null) {
          // 內(nèi)容布局,android.R.content
          mContentParent = generateLayout(mDecor);
          ...
      }
      // 設(shè)置標(biāo)題樣式等
      ... 
  }
}

WindowManagerGlobal

由ActivityThread -> handleResumeActivity 可知:
在onResume之后瘦锹,將DecorView添加到WindowManage(WindowManagerGlobal)
WindowManagerGlobal創(chuàng)建ViewRootImpl籍嘹,并將DecorView設(shè)置到ViewRootImpl

WindowManager.LayoutParams l = r.window.getAttributes();
wm.addView(decor, l);
public final class WindowManagerGlobal {

  private static IWindowManager sWindowManagerService;
  private static IWindowSession sWindowSession;

  public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
      ...
      // 創(chuàng)建ViewRootImpl
      ViewRootImpl root = new ViewRootImpl(view.getContext(), display);

      view.setLayoutParams(wparams);

      mViews.add(view);
      mRoots.add(root);
      mParams.add(wparams);
      
      ...
      
      // 給ViewRootImpl添加DecorView
      // 最后執(zhí)行這個(gè)操作,是因?yàn)樗鼤?huì)觸發(fā)消息
      root.setView(view, wparams, panelParentView, userId);
      
  }

  // 通過(guò)wms創(chuàng)建一個(gè)類(lèi)型為Session的Binder對(duì)象
  public static IWindowSession getWindowSession() {
       if (sWindowSession == null) {
            ...
            IWindowManager windowManager = getWindowManagerService();
            sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                });
            }
            return sWindowSession;
      }
  }

  // 獲取wms的代理
  public static IWindowManager getWindowManagerService() {
       if (sWindowManagerService == null) {
            sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
            ...
            return sWindowManagerService;
        }
  }

}

ViewRootImpl

通過(guò)IWindowSession于WindowManagerService交互弯院,完成window的添加等操作

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
        
   // mWindowSession是一個(gè)通過(guò)WMS獲取的Binder對(duì)象辱士,真正的實(shí)現(xiàn)類(lèi)是Session
   final IWindowSession mWindowSession;
   
   View mView;
   
   W mWindow = new W(this);
   
   // mWindowSession初始化
   public ViewRootImpl(Context context, Display display) {
        this(context, display, WindowManagerGlobal.getWindowSession(), false);
   }
   
   // 將Window添加到窗口管理器
   public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
            
        mView = view;
       ...
       
       // 在添加到窗口管理器之前請(qǐng)求一次布局
       // 以確保我們從系統(tǒng)接收任何其他事件之前進(jìn)行重新布局。
       requestLayout();
       
       // ViewRootImpl 通過(guò) IWindowSession 與 WMS 進(jìn)行交互的
       // 這是一個(gè)IPC的過(guò)程听绳,基于Binder的跨進(jìn)程通信颂碘。
       // 通過(guò)調(diào)用 addToDisplay, 將 mWindow 等參數(shù)傳遞給 WindowManagerService
       // 內(nèi)部執(zhí)行Window的添加等操作
       mWindowSession.addToDisplayAsUser(mWindow, ....);
       
       ...
       
       // 將ViewRootImpl設(shè)置為DecorView的parent (繼承ViewParent)
       view.assignParent(this);
       
       ...
   }         
   
   static class W extends IWindow.Stub {
    
       ... 
   }
}

1.Window的添加是通過(guò)IWindowSession建立起與WMS的連接椅挣。
2.IWindowSession是一個(gè)Binder對(duì)象头岔,其實(shí)現(xiàn)是Session,Session內(nèi)部通過(guò)調(diào)用WMS的addWindow方法進(jìn)行
Window的添加等操作鼠证,Window的狀態(tài)保存到了WindowState中
3.當(dāng)應(yīng)用啟動(dòng)第一個(gè)activity的時(shí)候峡竣,會(huì)請(qǐng)求WMS服務(wù)建立Binder進(jìn)程間通信服務(wù),WMS創(chuàng)建一個(gè)類(lèi)型為
Session的Binder對(duì)象量九,并將這個(gè)Binder對(duì)象返回給應(yīng)用進(jìn)程

Window的添加大致流程:
-> WindowManager(WindowManagerImpl)
-> WindowManagerGlobal>addView
-> ViewRootImpl>setView>IWindowSession>addToDisplay
-> (IPC)Session>addToDisplay
-> WindowManagerService>addWindow

總結(jié)

1.Activity啟動(dòng)時(shí)适掰,由ActivityThread.handleLaunchActivity創(chuàng)建Activity,并執(zhí)行Activity.attach方法,
然后回調(diào)onCreate
2.Activity.attach創(chuàng)建一個(gè)PhoneWindow
3.PhoneWindow創(chuàng)建DecorView荠列,并將contentView添加到DecorView
4.ActivityThread.handleResumeActivity类浪,回調(diào)onResume,然后獲取window的DecorView添加到WM中
5.WM創(chuàng)建ViewRootImpl弯予,并調(diào)用ViewRootImpl.setView將DecorView設(shè)置到ViewRootImpl中
6.ViewRootImpl調(diào)用requestLayout()方法來(lái)請(qǐng)求繪制布局
7.ViewRootImpl通過(guò)WMS獲取Session的代理對(duì)象IWindowSession
8.IWindowSession將window的binder代理W添加到WMS中

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末戚宦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锈嫩,更是在濱河造成了極大的恐慌受楼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呼寸,死亡現(xiàn)場(chǎng)離奇詭異艳汽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)对雪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)河狐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事馋艺≌じ桑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵捐祠,是天一觀的道長(zhǎng)碱鳞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)踱蛀,這世上最難降的妖魔是什么窿给? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮率拒,結(jié)果婚禮上崩泡,老公的妹妹穿的比我還像新娘。我一直安慰自己猬膨,他們只是感情好角撞,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著寥掐,像睡著了一般靴寂。 火紅的嫁衣襯著肌膚如雪磷蜀。 梳的紋絲不亂的頭發(fā)上召耘,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音褐隆,去河邊找鬼污它。 笑死,一個(gè)胖子當(dāng)著我的面吹牛庶弃,可吹牛的內(nèi)容都是我干的衫贬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼歇攻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼固惯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起缴守,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤葬毫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后屡穗,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贴捡,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年村砂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烂斋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖汛骂,靈堂內(nèi)的尸體忽然破棺而出罕模,到底是詐尸還是另有隱情,我是刑警寧澤帘瞭,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布手销,位于F島的核電站,受9級(jí)特大地震影響图张,放射性物質(zhì)發(fā)生泄漏锋拖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一祸轮、第九天 我趴在偏房一處隱蔽的房頂上張望兽埃。 院中可真熱鬧,春花似錦适袜、人聲如沸柄错。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)售貌。三九已至,卻和暖如春疫萤,著一層夾襖步出監(jiān)牢的瞬間颂跨,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工扯饶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恒削,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓尾序,卻偏偏與公主長(zhǎng)得像钓丰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子每币,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容