亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Activity的Window創建過程

2019-11-09 13:57:06
字體:
來源:轉載
供稿:網友

Activity的Window創建過程

在 Adroid 中 Window 表示一個窗口的概念,任何能展示的視圖都必須是掛載于 Window 上的,例如 Activity,Toast,Dialog,PopupWindow 等控件都有承載展示給用戶的視圖的 Window。而 Window 是一個抽線類,它的直接子類是 PhoneWindow。Window 可以接受事件,例如觸摸事件,鍵盤的響應事件等。在事件傳遞機制就是將事件首先傳遞給 Window,然后再由 Window 傳遞給掛載在 Window 中的 DecorView 中,之后再傳遞到對應的 View 上。除此之后,在 Activity#setContentView(layoutId) 內部也是去調用 PhoneWindow#setContentView(layoutId) 去實現。

1、 從 setContentView(layoutId)了解 Activity 中 window的創建

1.1、 setContentView(layoutId)

public void setContentView(@LayoutRes int layoutResID) { //getWindow 就是 activity 對應的 Window 的子類 PhoneWindow getWindow().setContentView(layoutResID); initWindowDecorActionBar();}

1.2、 Window 是在哪里實例化?

getWindow() 就是 Activity 所依賴的 Window對象,而它是在哪里創建呢?查看源碼,可以知道 PhoneWindow 就是在 Activity#attach() 中被調用的。在這個方法主要做的事是:(1)創建 PhoneWindow 對象 ;(2) 設置事件監聽,接受觸摸事件,鍵盤輸入等事件;(3)給 activity 的成員變量賦值。而 attach() 方法它是在 ActivityThread#performLaunchActivity() 方法中調用,這里涉及到 Activity 的生命周期的分析 ,這里不是討論的終重點,先行跳過?,F在呢,我們就知道了 activity 中的 window 在哪里創建的了。

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) { attachBaseContext(context); mFragments.attachHost(null /*parent*/); mWindow = new PhoneWindow(this);//(1)創建 PhoneWindow 對象 mWindow.setCallback(this);// (2)設置事件監聽器 mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPRivateFactory(this); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } if (info.uiOptions != 0) { mWindow.setUiOptions(info.uiOptions); } // (3)activity 成員變量的賦值 mUiThread = Thread.currentThread(); mMainThread = aThread; mInstrumentation = instr; mToken = token; mIdent = ident; mApplication = application; mIntent = intent; mReferrer = referrer; mComponent = intent.getComponent(); mActivityInfo = info; mTitle = title; mParent = parent; mEmbeddedID = id; mLastNonConfigurationInstances = lastNonConfigurationInstances; if (voiceInteractor != null) { if (lastNonConfigurationInstances != null) { mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor; } else { mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this, Looper.myLooper()); } } mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); if (mParent != null) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); mCurrentConfig = config; }

1.2、 繼續了解 PhoneWindow#setContentView(layoutId)

在瀏覽源碼之前,需要了解幾個概念

DecorView 就是 Activity 的根視圖,它是一個 FrameLayout 視圖。有標題欄和內容欄,不過不同版本可能有差異。mParentContent 就是 DecorView 的直接子 View,它是 Decor 的內容欄。它有指定的 id :android.R.id.content,通過 setContentView(layoutId) 的 layoutId 對應的 View 就是掛載在 mContentParent 上的。

初次調用時先檢測 mContentParent 是否為 null,當該值為 null 時,就去 generateDecor() 裝載一個根視圖 Decor。然后調用 mContentParent.addView(view, params) 往 mContentParent 掛載 setContentView(layoutId) 對應的 View。

@Overridepublic void setContentView(View view, ViewGroup.LayoutParams params) { // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window // decor, when theme attributes and the like are crystalized. Do not check the feature // before this happens. if (mContentParent == null) {//mContentParent 就是 DecorView 中的一級子View installDecor();//裝載一個 Activity 的根視圖 } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { view.setLayoutParams(params); final Scene newScene = new Scene(mContentParent, view); transitionTo(newScene); } else { mContentParent.addView(view, params);// 往 mContentParent 掛載 setContentView(layoutId) 對應的 View。 } mContentParent.requestApplyInsets();}private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); // 創建 Activity 的根視圖 ... } if (mContentParent == null) { mContentParent = generateLayout(mDecor); //給 mContentParent 賦值 ... }}//將內容欄添加到 Decor 中protected ViewGroup generateLayout(DecorView decor) { ... View in = mLayoutInflater.inflate(layoutResource, null); decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); ...}

1.3、 Activity 中的 onContentChanged()方法通知 Activity 視圖發生了改變

當 Decor 初始化完畢之后,會通過在 Callback#onContentChanged(),表示 Decor 已經完成初始化操作.這個 Callback 就是在 Activity#attach() 方法設置的,因為在 Activity 中實現了 Callback 接口,因此該方法會回調到 Activity 中的 onContentChanged()方法中,不過這個方法是空實現,用戶可已重寫該方法。

final Callback cb = getCallback();// 在 DecorView 初始化完畢之后的回調 onContentChanged()方法。if (cb != null && !isDestroyed()) { cb.onContentChanged();}

1.4、 往 Window 添加 DecorView

現在 Window 創建好了,對應的 DecorView 也初始完畢了,接下來就是發揮 WindowManager 的作用了,那就是往 Window 中添加 DecorView了。在這個過程涉及到 Activity 的生命周期的回調,我們這里暫且跳過,直接切入 Window 添加 DecorView 的源碼。

1.4.1、 ActivityThread#handleResumeActivity

Activity 的生命周期的回調是一個 ipC 過程,在 ActivityThread#handleResumeActivity() 就是負責 Activity#onResume() 生命周期的回調。在 handleResumeActivity 方法內部調用 wm.addView(decor, l); 將 DecorView 添加到 Activity 對應的 Window 中。這個過程實際上是有 WindowManager 去完成的,每一 Window 都會對應一個 WindowManager,通過 WindowManager 去往 Window 中 addView,removeView或者是 updateViewLayout 操作。

//#handleResumeActivity 代碼片段final Activity a = r.activity;if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE);//設置 DecorView 不可見 ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; wm.addView(decor, l);//往 Window 添加 View }}

1.4.2、 Wm.addView 的過程

WindowManager 是一個接口,因此 addView 的操作是有其子 View 去實現的,那么它的子 View 是誰呢?下面的代碼可以看到 WindowManager 的實現類就是 WindowManagerImpl。

public final class WindowManagerImpl implements WindowManager {}

1.4.3、 WindowManagerImpl.addView 的過程

WindowManagerImpl#addView 的操作都是交給 WindowManagerGlobal 的類去執行。

@Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mDisplay, mParentWindow); }

1.4.4、 WindowManagerGlobal.addView 的過程

WindowManagerGlobal 是單例的方式提供對象的,內部維護了 mView,mRoots,mParams,mDyingViews 等集合。

mViews 保存的就是添加到 Window 中的 View 對象。mRoots 保存的就是 每一個 Window 對應的 ViewRootImpl 對象。mDyingViews 保存的是哪些調用了 removeView 但是刪除操作還未完成的 Window 對象對應的 View。mParams 保存的是每一個 Window 的布局參數。// 懶漢式單例模式public static WindowManagerGlobal getInstance() { synchronized (WindowManagerGlobal.class) { if (sDefaultWindowManager == null) { sDefaultWindowManager = new WindowManagerGlobal(); } return sDefaultWindowManager; }}

在 addView 中創建 Window 對應的 ViewRootImpl 對象。并且往mViews,mRoots,mParams,mDyingViews 中保存當前 View 的信息。 最后調用 root.setView(view, wparams, panelParentView);

public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { //校驗操作 final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; ViewRootImpl root; View panelParentView = null; synchronized (mLock) { 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. } //創建 ViewRootImpl 對象。 root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); //保存到集合中 mViews.add(view); mRoots.add(root); mParams.add(wparams); } // 調用 View 的繪制代碼 root.setView(view, wparams, panelParentView);}

1.4.5、DecorView 真正顯示過出來

現在 Window 對應的視圖已經準備好了,但是該仍然是不可見的,接下來繼續看ActivityThread#handleResumeActivity 代碼。這時會去調用 Activity#makeVisible()方法。因為在 1.4.1、 ActivityThread#handleResumeActivity 中 DecorView 被設置為 invisible 因此在這時Decor 會被設置為 View.VISIBLE。至此 View 就真正的顯示出來了。

//ActivityThread#handleResumeActivityr.activity.mVisibleFromServer = true;if (r.activity.mVisibleFromClient) { r.activity.makeVisible();}//Activity#makeVisible()void makeVisible() { if (!mWindowAdded) {//判斷 DecorView 是否被添加到 Window 中 ViewManager wm = getWindowManager(); wm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; } mDecor.setVisibility(View.VISIBLE);//讓 View 設置為可見}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美午夜片欧美片在线观看| 欧美大片在线看| 91色在线观看| 亚洲精品日韩丝袜精品| 国产精品欧美激情在线播放| 国产在线观看91精品一区| 日韩欧美国产一区二区| 综合欧美国产视频二区| 亚洲欧美一区二区三区在线| 国产亚洲精品美女| 国产精品亚发布| 亚洲国产成人爱av在线播放| 精品国产91久久久久久| 美女国内精品自产拍在线播放| 俺去了亚洲欧美日韩| 欧美伊久线香蕉线新在线| 亚洲国产精品国自产拍av秋霞| 欧美xxxx综合视频| 国产午夜精品一区理论片飘花| 国产成人高清激情视频在线观看| 精品中文字幕在线观看| 亚洲午夜久久久影院| 亚洲国产精品悠悠久久琪琪| 国产精品中文字幕久久久| 久久夜精品香蕉| 亚洲香蕉伊综合在人在线视看| 一区二区三区四区在线观看视频| 亚洲色图欧美制服丝袜另类第一页| 日韩视频中文字幕| 欧美激情亚洲精品| 久久综合电影一区| 日韩在线观看网站| 国产精品亚洲欧美导航| 亚洲国产天堂久久国产91| 亚洲色图欧美制服丝袜另类第一页| 国产精品劲爆视频| 中文字幕亚洲情99在线| 亚洲网站在线观看| 97国产在线视频| 国内久久久精品| 国产精品第1页| 日本视频久久久| 日韩av在线看| 久久精品亚洲94久久精品| 亚洲第一免费播放区| 一本色道久久88精品综合| 日韩成人在线免费观看| 91av免费观看91av精品在线| 自拍偷拍亚洲精品| 日韩成人黄色av| 中文字幕日韩精品在线观看| 成人黄色av网站| 欧美黑人一区二区三区| 国产精品网址在线| 久久av红桃一区二区小说| 亚洲第一视频网站| xxx成人少妇69| 国产精品久久久久久久久影视| 久久久久久亚洲| 亚洲国产精品成人精品| 国产mv免费观看入口亚洲| 国产视频亚洲精品| 久久综合久中文字幕青草| 欧美日韩一区二区三区在线免费观看| 亚洲激情视频在线观看| 欧美日韩亚洲国产一区| 久久久久久久久久久免费精品| 欧美日韩一区二区免费视频| 国模视频一区二区三区| 一本色道久久综合狠狠躁篇的优点| 黄色成人av在线| 欧美性猛交xxxx免费看漫画| 日韩在线观看免费全集电视剧网站| 国产精品尤物福利片在线观看| 久久久久久久久久婷婷| 青青精品视频播放| 成人性生交大片免费看小说| 一本大道亚洲视频| 超在线视频97| 欧美日韩色婷婷| 国产精品久久久久久久美男| 欧美大片在线免费观看| 成人激情在线播放| 亚洲美女www午夜| 欧美日韩中文字幕在线| 一区二区三区 在线观看视| 久久中国妇女中文字幕| 日韩高清中文字幕| 欧美黄色三级网站| 91av在线网站| 日韩一区二区三区国产| 亚洲无线码在线一区观看| 国产区精品在线观看| 欧美日韩人人澡狠狠躁视频| 国产在线高清精品| www日韩欧美| 亚洲成人久久久| 成人精品视频久久久久| 91亚洲国产成人久久精品网站| 成人免费直播live| 久久久久久美女| 亚洲伊人一本大道中文字幕| 亚洲毛片在线观看.| 国产精品黄页免费高清在线观看| 欧美成人精品在线| 久久最新资源网| 久久成人精品一区二区三区| 亚洲欧美日韩天堂| 一区二区三区视频在线| 国产精品久久久久久久午夜| 国产综合色香蕉精品| 日韩精品免费在线视频观看| 日韩中文字幕国产精品| 午夜精品一区二区三区av| 欧美疯狂性受xxxxx另类| 亚洲第一区中文99精品| 精品福利樱桃av导航| 久久黄色av网站| 日本成人在线视频网址| 性色av一区二区三区在线观看| 欧美xxxx14xxxxx性爽| 91精品91久久久久久| 伊人精品在线观看| 国产精品吊钟奶在线| 日韩免费看的电影电视剧大全| 日韩亚洲第一页| 国产成人鲁鲁免费视频a| 丝袜美腿精品国产二区| 91精品久久久久久久久久久久久久| 亚洲男人天堂2023| 欧洲午夜精品久久久| 欧美理论电影在线观看| 亚洲综合视频1区| 国产精品极品美女在线观看免费| 亚洲一级黄色片| 欧美三级欧美成人高清www| 成人免费观看网址| 亚洲精品久久在线| 国产免费一区视频观看免费| 国产精品欧美激情| 中文综合在线观看| 97视频在线播放| 欧美日韩国产限制| 亚洲性无码av在线| 综合国产在线视频| 亚洲在线免费看| 亚洲免费影视第一页| 亚洲视频国产视频| 成人两性免费视频| 精品成人国产在线观看男人呻吟| 欧美成人精品在线播放| 97视频免费看| 欧美精品videosex极品1| 成人97在线观看视频| 国产成人在线精品| 激情亚洲一区二区三区四区| 国产欧美一区二区三区视频| 国产精品免费观看在线| 成人免费在线网址| 中文字幕亚洲天堂| 韩国美女主播一区| 日韩亚洲欧美中文高清在线| 中文字幕久热精品在线视频| 国产va免费精品高清在线|