流程圖
(大體流程矛市,從Activity接受啟動開始)
源碼分析
基于API 23
Window創(chuàng)建
ActivityThread.handleLaunchActivity
ActivityThread.performLaunchActivity
ActivityThread處理并執(zhí)行Activity啟動
//ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
//獲取WindowManagerService的Binder引用(proxy端)拗秘。
WindowManagerGlobal.initialize();
//執(zhí)行Activity的onCreate,onStart,onResotreInstanceState方法
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
...
//執(zhí)行Activity的onResume方法.
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//通過類加載器創(chuàng)建Activity
Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
//通過LoadedApk的makeApplication方法來創(chuàng)建Application對象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
...
// 執(zhí)行 attach 方法
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);
...
//onCreate
mInstrumentation.callActivityOnCreate(activity, r.state);
//onStart
activity.performStart();
}
return activity;
}
Activity.attach
- 構(gòu)造PhoneWindow (Window唯一具體實現(xiàn))
- 設(shè)置自身為Window的Callback秒紧,從而Activity能作為callback接受window的key和touch事件
- 初始化且設(shè)置WindowManager交排,每個Activity對應(yīng)一個WindowManager盛撑,通過WM與WMS進行通信
final void attach(...) {
//綁定上下文
attachBaseContext(context);
//創(chuàng)建Window,PhoneWindow是Window的唯一具體實現(xiàn)類
mWindow = new PhoneWindow(this, window);//此處的window==null植阴,但不影響
mWindow.setWindowControllerCallback(this);
// 設(shè)置 Window.Callback
mWindow.setCallback(this);
...
//設(shè)置WindowManager
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());
}
//創(chuàng)建完后通過getWindowManager就可以得到WindowManager實例
mWindowManager = mWindow.getWindowManager();//其實它是WindowManagerImpl
}
Window添加View過程
前面在handleLauncherActivity完成了PhoneWindow的創(chuàng)建過程涧卵,下面我們繼續(xù)查看Activity執(zhí)行生命周期handleResumeActivity方法勤家,查看Activity對應(yīng)View被加載到PhoneWindow容器過程
ActivityThread.handleResumeActivity
- 獲取ActivityClientRecord,將對應(yīng)DecorView設(shè)置為不可見柳恐,因為當(dāng)前View還未繪制
- 通過Window對應(yīng)的WindowManager執(zhí)行addView(decor伐脖,l)操作
- View繪制完成后,會將decorView設(shè)置可見乐设,展示該Activity對應(yīng)內(nèi)容讼庇,最后onResume完成
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
//把activity數(shù)據(jù)記錄更新到ActivityClientRecord
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);//不可見
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
...
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);// 把decor添加到窗口上
}
}
//屏幕參數(shù)發(fā)生了改變
performConfigurationChanged(r.activity, r.tmpConfig);
WindowManager.LayoutParams l = r.window.getAttributes();
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
wm.updateViewLayout(decor, l);//更新窗口狀態(tài)
}
...
if (r.activity.mVisibleFromClient) {
//已經(jīng)成功添加到窗口上了(繪制和事件接收),設(shè)置為可見
r.activity.makeVisible();
}
//通知ActivityManagerService伤提,Activity完成Resumed
ActivityManagerNative.getDefault().activityResumed(token);
}
}
WindowManagerImply.addView
WindowManagerGlobal.addView
- WindowManagerImpl的全局變量通過單例模式初始化了WindowManagerGlobal巫俺,(一個進程一個WMG對象)
- Window管理類添加View過程,創(chuàng)建ViewRootImpl肿男,將View處理操作交給ViewRootImpl實現(xiàn)
// WindowManagerImply
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
// WindowManagerGlobal
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
synchronized (mLock) {
...
// 創(chuàng)建ViewRootImpl介汹,并將View與之綁定
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view); // 將當(dāng)前view添加到mView集合中
mRoots.add(root); // 將當(dāng)前root添加mRoots集合中
mParams.add(wparams); // 將當(dāng)前window的params添加到mParams集合中
}
// setView 完成View的繪制流程却嗡,并添加到window上
root.setView(view, wparams, panelParentView);
}
ViewRootImpl.setView
- ViewRootImpl構(gòu)建過程中,會通過WindowManagerGlobal的getWindowSession(static方法)獲取IWindowSession即WindowSession
- 執(zhí)行requestLayout方法完成View的繪制流程
- 通過WindowSession與WindowManagerService通信嘹承,將View和InputChannel添加到WMS窗价,從而展示View并可以接受輸入事件
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
int res
requestLayout();//執(zhí)行 View的繪制流程
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
// 創(chuàng)建InputChannel
mInputChannel = new InputChannel();
}
try {
//通過WindowSession進行IPC調(diào)用,將View添加到Window上
//mWindow即W類叹卷,用來接收WmS信息
//同時通過InputChannel接收觸摸事件回調(diào)
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
}
...
//處理觸摸事件回調(diào)
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
WindowSession.addToDisplay
- Session執(zhí)行addToDisplay方法撼港,通過調(diào)用成員變量WMS進行addWindow操作
public int addToDisplay(...) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
WindowManagerService.addWindow
- 創(chuàng)建WindowState,保存Window狀態(tài)
- 調(diào)整LayoutParams參數(shù)骤竹、設(shè)置input帝牡、設(shè)置window zOrder
- 執(zhí)行WindowState的attach(創(chuàng)建Surface過程,詳情見下一篇)
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,InputChannel outInputChannel) {
... // 一堆check邏輯
WindowToken token = mTokenMap.get(attrs.token);
//創(chuàng)建 WindowState
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
...
//調(diào)整 WindowManager 的 LayoutParams 參數(shù)
mPolicy.adjustWindowParamsLw(win.mAttrs);
res = mPolicy.prepareAddWindowLw(win, attrs);
addWindowToListInOrderLocked(win, true);
// 設(shè)置 input
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
// 創(chuàng)建 Surface 與 SurfaceFlinger 通信蒙揣,
win.attach();
mWindowMap.put(client.asBinder(), win);
if (win.canReceiveKeys()) {
//當(dāng)該窗口能接收按鍵事件靶溜,則更新聚焦窗口
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);
}
assignLayersLocked(displayContent.getWindowList());
...
}
推薦閱讀:圖形系統(tǒng)總結(jié)
參考
Android Window 機制探索