緣起
筆者為什么會挑這個話題,是因為長時間以來我自己對這2個方法一直有些疑惑,比如:
- 為啥叫
onAttachedToWindow
而不是onAttachedToActivity
,Window
又是什么,在哪里?畢竟我們平時絕大多數時候接觸到的是Activity
啊; Activity
有明確的生命周期方法,但View
卻沒有,那么這2個方法可以認為是View
的嗎?它們又何時會被調用呢?
慢慢地隨着在這一行逐漸深入,閱讀了些系統源碼,開始對這些問題有了自己的答案或者說更加深刻的認識。這篇文章嘗試將筆者的這些理解、認識說清楚,希望能幫助更多人加深認識。
onAttachedToWindow的調用過程
我們在前面Activity啟動過程的文章中說過,在ActivityThread.handleResumeActivity
的過程中,會將Act的DecorView添加到WindowManager
中,可能很多人一開始會覺得WindowManager
是一個具體的類,但是實際上它卻只是個繼承了ViewManager
的接口,具體代碼如下:
/** Interface to let you add and remove child views to an Activity. To get an instance * of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. */ public interface ViewManager { /** * Assign the passed LayoutParams to the passed View and add the view to the window. * <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming * errors, such as adding a second view to a window without removing the first view. * <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a * secondary {@link Display} and the specified display can't be found * (see {@link android.app.Presentation}). * @param view The view to be added to this window. * @param params The LayoutParams to assign to view. */ public void addView(View view, ViewGroup.LayoutParams params); public void updateViewLayout(View view, ViewGroup.LayoutParams params); public void removeView(View view); }
而WindowManager
的樣子差不多是這樣,如下圖:

WindowManager源碼
當在ActivityThread.handleResumeActivity()
方法中調用WindowManager.addView()
方法時,最終是調去了
WindowManagerImpl.addView() --> WindowManagerGlobal.addView()
這里我們看下最終調用到的代碼:
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (display == null) { throw new IllegalArgumentException("display must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); } else { // If there's no parent, then hardware acceleration for this view is // set from the application's hardware acceleration setting. final Context context = view.getContext(); if (context != null && (context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } } ViewRootImpl root; View panelParentView = null; synchronized (mLock) { // Start watching for system property changes. if (mSystemPropertyUpdater == null) { mSystemPropertyUpdater = new Runnable() { @Override public void run() { synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { mRoots.get(i).loadSystemProperties(); } } } }; SystemProperties.addChangeCallback(mSystemPropertyUpdater); } int index = findViewLocked(view, false); if (index >= 0) { if (mDyingViews.contains(view)) { // Don't wait for MSG_DIE to make it's way through root's queue. mRoots.get(index).doDie(); } else { throw new IllegalStateException("View " + view + " has already been added to the window manager."); } // The previous removeView() had not completed executing. Now it has. } // If this is a panel window, then find the window it is being // attached to for future reference. if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && wparams.type <= WindowManager