簡(jiǎn)介
我們知道在Android系統(tǒng)中Activity代表一個(gè)窗口的顯示,甚至初學(xué)者認(rèn)為Activity就是一個(gè)顯示窗口,在Activity中能夠完成顯示的所有功能,但是這樣理解有偏差,Activity之所以能承載顯示是由于內(nèi)部存在很多與顯示相關(guān)的核心類,Activity只是通過(guò)一些管理方法和回調(diào)函去處理這些核心類的核心方法。所以我們應(yīng)該更深層次的接觸Activity。
由于筆者之前接觸界面開(kāi)發(fā)很少,甚至沒(méi)有怎么接觸界面開(kāi)發(fā),所以對(duì)Activity的源碼也不懂,我也是抱著學(xué)習(xí)的心態(tài),去嘗試研究Activity與顯示的關(guān)系,所以有什么不對(duì)或者需要筆者完善的地方希望讀者能夠提出來(lái),只有提出問(wèn)題,我才能去主動(dòng)探求答案找尋真理。更好的分享給大家,達(dá)到共同學(xué)習(xí)共同進(jìn)步的目的。好了話不多少進(jìn)入今天的主題。
源碼分析
關(guān)于Activity的啟動(dòng)流程并不是今天的重點(diǎn),所以我大概提下Activity的啟動(dòng)過(guò)程,我們重點(diǎn)在于后面
我們之前分析過(guò)APP進(jìn)程啟動(dòng)的過(guò)程會(huì)啟動(dòng)Activity,我們就從進(jìn)程啟動(dòng)后進(jìn)入Activity啟動(dòng)流程分析
AMS.startProcessLocked
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
...
////只有當(dāng)系統(tǒng)啟動(dòng)完,或者app允許啟動(dòng)過(guò)程允許,則會(huì)true
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
thread.bindApplication(...);
if (normalMode) {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
}
...
}
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFrontStack(stack)) {
continue;
}
//獲取前臺(tái)stack中棧頂?shù)谝粋€(gè)非finishing的Activity
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//真正的啟動(dòng)Activity
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
throw e;
}
}
}
}
}
if (!didSomething) {
//啟動(dòng)Activity不成功,則確保有可見(jiàn)的Activity
ensureActivitiesVisibleLocked(null, 0);
}
return didSomething;
}
ASS.realStartActivityLocked
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
app.thread.scheduleLaunchActivity(...);
}
ApplicationThread.java
public final void scheduleLaunchActivity(...) {
sendMessage(H.LAUNCH_ACTIVITY, r);
}
ActivityThread.java::H
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
} break;
...
}
}
ActivityThread.handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
unscheduleGcIdler();
mSomeActivitiesChanged = true;
//最終回調(diào)目標(biāo)Activity的onConfigurationChanged()
handleConfigurationChanged(null, null);
//初始化wms
WindowManagerGlobal.initialize();
//最終回調(diào)目標(biāo)Activity的onCreate
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//最終回調(diào)目標(biāo)Activity的onStart,onResume.
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
r.paused = true;
}
} else {
//存在error則停止該Activity
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
}
}
我們現(xiàn)在涉及到了兩個(gè)關(guān)鍵點(diǎn)
- 現(xiàn)在
Activity a = performLaunchActivity(r, customIntent);Activity生產(chǎn)出來(lái)了 - 最終調(diào)用handleResumeActivity()目前也看不出這個(gè)方法干啥
我們就針對(duì)這兩個(gè)核心調(diào)用進(jìn)行分析
1. Activity a = performLaunchActivity(r, customIntent)
ActivityThread.performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
//創(chuàng)建Application對(duì)象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
...
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (Exception e) {
...
}
return activity;
}
我們通過(guò)這段代碼可以看出來(lái)
- 根據(jù)類名使用反射創(chuàng)建一個(gè)Activity實(shí)例化對(duì)象
- 調(diào)用Activity的onCreate方法
我們結(jié)合上面可以知道是在主線程中執(zhí)行,所以Activity.onCreate()方法是在主線程中調(diào)用的,一般情況下我們會(huì)在onCreate()方法中使用setContentView()進(jìn)行設(shè)置UI的外觀。
handleResumeActivity
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
...
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;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
...
}
這里有幾個(gè)重點(diǎn):
- r.window = r.activity.getWindow()出現(xiàn)了window
- View decor = r.window.getDecorView()出現(xiàn)了view
- ViewManager wm = a.getWindowManager()出現(xiàn)了ViewManager
這部分和UI有關(guān),但是我們?cè)谶@塊并不知道哪里來(lái)的這些變量,突然就冒出來(lái)讓我們有點(diǎn)不知所措。所以我們回想一下,剛才調(diào)用了onCreate()之后才發(fā)生這些的,onCreate()是不是我們要調(diào)用setContentView設(shè)置一些什么東東呢哈哈。
setContentView()
Activity.java
private Window mWindow;
public void setContentView(View view) {
getWindow().setContentView(view);
initWindowDecorActionBar();
}
public Window getWindow() {
return mWindow;
}
mWindow是什么,在哪里創(chuàng)建的?
那么我們就只能在Activity創(chuàng)建的過(guò)程中尋找答案.
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
Instrumentation.java
public Activity newActivity(Class<?> clazz, Context context,
IBinder token, Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance) throws InstantiationException,
IllegalAccessException {
Activity activity = (Activity)clazz.newInstance();
ActivityThread aThread = null;
activity.attach(context, aThread, this, token, 0, application, intent,
info, title, parent, id,
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
new Configuration(), null, null);
return activity;
}
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);
mWindow.setCallback(this);
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);
}
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;
}
在Context中定義了:public static final String WINDOW_SERVICE = "window";
我們看到了
- mWindow = new PhoneWindow(this);
- mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)...);
所以這個(gè)時(shí)候我們明白在Activity中mWindow是PhoneWindow對(duì)象,并且mWindow設(shè)置了名稱為window的服務(wù)
我們繼續(xù)回到setContentView的這個(gè)話題,我們現(xiàn)在知道是調(diào)用PhoneWindow的setContentView了
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
調(diào)用了兩個(gè)核心:
- installDecor()
- mContentParent.requestApplyInsets();
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();// return new DecorView(getContext(), -1);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent);
if (decorContentParent != null) {
mDecorContentParent = decorContentParent;
mDecorContentParent.setWindowCallback(getCallback());
if (mDecorContentParent.getTitle() == null) {
mDecorContentParent.setWindowTitle(mTitle);
}
...
}
generateLayout()
public class PhoneWindow extends Window implements MenuBuilder.Callback {
public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
protected ViewGroup generateLayout(DecorView decor) {
...
mDecor.startChanging();
//此時(shí)的layoutResource代表整個(gè)界面
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
return contentParent;
}
Window.java
public View findViewById(@IdRes int id) {
return getDecorView().findViewById(id);
}
代碼可以看出來(lái),我們先加載View然后添加到decor中,對(duì)于這個(gè)contentid也只不多是DecorView的一部分。
所以我們通過(guò)包含關(guān)系形容他們
PhoneWindow
DecorView
MyView
我們?cè)谕ㄟ^(guò)文字來(lái)描述一下這個(gè)關(guān)系
我們?cè)贏ctivity通過(guò)反射創(chuàng)建之后會(huì)調(diào)用Activity.attach()方法在這個(gè)方法中會(huì)創(chuàng)建PhoneWindow和對(duì)PhoneWindow設(shè)置名稱是window的服務(wù),當(dāng)我們?cè)贏ctivity.onCreate()方法中使用setContentView的時(shí)候會(huì)創(chuàng)建DecorView,然后將整個(gè)一些元素添加到DecorView中
所以我們?cè)贏ctivity中的那些界面其實(shí)最根部的設(shè)置是由DecorView這個(gè)View保存設(shè)置的。
目前為止我們通過(guò):
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
...
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;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
...
}
這個(gè)方法得知,現(xiàn)在PhoneWindow,DecorView都有了,只是欠缺ViewManager,我們需要分析ViewManager
public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
private WindowManager mWindowManager;
ViewManager wm = a.getWindowManager();//return mWindowManager
我們?cè)赼ttach方法中進(jìn)行創(chuàng)建
final void attach(...) {
attachBaseContext(context);
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
...);
...
mWindowManager = mWindow.getWindowManager();
}
我們知道m(xù)Window是PhoneWindow對(duì)象,在其父類Window中實(shí)現(xiàn)了getWindowManager方法:
public WindowManager getWindowManager() {
return mWindowManager;
}
同樣在PhoneWindow的父類Window中構(gòu)造并且設(shè)置了WindowManager
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
WindowManagerImpl.java
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mDisplay, parentWindow);
}
到這里我們就知道對(duì)應(yīng)ViewManager是WindowManagerImpl對(duì)象
也就是說(shuō)我們?cè)贏ctivity.attach()中創(chuàng)建了WindowManagerImpl對(duì)象然后在handleResumeActivity方法中利用WindowManagerImpl將產(chǎn)生的decorView添加到wm中。
在小結(jié):
ActivityThread.handleLaunchActivity()
Activity a = performLaunchActivity()
activity = mInstrumentation.newActivity()
activity.attach()
mWindow = new PhoneWindow(this);
mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)...);
mWindowManager = ((WindowManagerImpl)mContext.getSystemService("window")).createLocalWindowManager(this);
return new WindowManagerImpl(mDisplay, parentWindow)
mWindowManager = mWindow.getWindowManager()
mInstrumentation.callActivityOnCreate(activity...)
activity.performCreate(...)
onCreate(...)
setContentView(R.id.xx)
getWindow().setContentView(layoutResID);
PhoneWindow.installDecor()
generateDecor()
return new DecorView();
handleResumeActivity()
wm.addView(decor...)
mGlobal.addView(view...)
root = new ViewRootImpl(...)
Surface mSurface = new Surface()//成員變量
mWindowSession = WindowManagerGlobal.getWindowSession()
IWindowManager windowManager = getWindowManagerService()
sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"))
sWindowSession = windowManager.openSession()
Session session = new Session()//在WMS中
mWindow = new W(this)//構(gòu)造函數(shù)
root.setView(view...)
mWindowSession.addToDisplay(mWindow...)
return mService.addWindow(...)//mService是WMS
token = new WindowToken(...)
WindowState win = new WindowState(...)
win.attach()
mSession.windowAddedLocked();
mSurfaceSession = new SurfaceSession();
mWindowMap.put(client.asBinder(), win)//將這個(gè)window加入列表中
requestLayout()
scheduleTraversals()
run(){doTraversal()}
performTraversals()
我們?cè)赼pp進(jìn)程啟動(dòng)的時(shí)候會(huì)初始android環(huán)境,然后過(guò)程中會(huì)啟動(dòng)activity,在啟動(dòng)activity的時(shí)候是通過(guò)反射方法生成Activity對(duì)象調(diào)用attach之后然后會(huì)調(diào)用Activity的OnCreate()方法在調(diào)用attach過(guò)程中會(huì)生成一些核心的對(duì)象其中主要有PhoneWindow對(duì)象與WindowManagerImpl對(duì)象,當(dāng)調(diào)用onCreate()的時(shí)候會(huì)使用setContentView做設(shè)置布局,這個(gè)時(shí)候就會(huì)產(chǎn)生mDecor(DecorView)最后執(zhí)行到handleResumeActivity這個(gè)方法也就是對(duì)應(yīng)Activity聲明周期回調(diào)的OnResume方法,此時(shí)將DecorView對(duì)象添加到WindowManagerImpl中進(jìn)行管理。
后面大概的內(nèi)容還有個(gè)ViewRoot,Surface,WMS,RawBuffer等等。因?yàn)槲覀兊侥壳盀橹怪繢ecorView是根布局,但是我們并牽扯到繪制,按鍵監(jiān)聽(tīng)消息通信方面的知識(shí)所以我們以后的分析會(huì)更難,因?yàn)闋砍兜酵ㄐ拍K與WMS的管理模塊了,不要灰心一點(diǎn)點(diǎn)看總會(huì)進(jìn)步。
ViewRoot剖析
為什么我們要剖析ViewRoot呢?到目前為止我們發(fā)現(xiàn)我們并沒(méi)有與任何繪制有關(guān)的進(jìn)程進(jìn)行通信所以我們需要繼續(xù)剖析Android系統(tǒng)如何進(jìn)行繪制管理的。所以ViewRoot是與WMS,Surface打交道的樞紐。
我們?cè)贏ctivityThread.handleResumActivity()的時(shí)候會(huì)有如下代碼:
ActivityThread.handleResumActivity(){
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;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
....
}
}
在這里面調(diào)用ViewManager的add方法,但是是誰(shuí)實(shí)現(xiàn)了ViewManager呢,ViewManager在這里只是接口。
我們這里具體是在attach中得到wm的:
Activity.attach()
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();
其中setWindowManager:
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
WindowManagerImpl.createLocalWindowManager()
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mDisplay, parentWindow);
}
注意了主角來(lái)了:
也就是說(shuō)我們上面:
ActivityThread.handleResumActivity(){
...
wm.addView(decor, l);
...
}
是調(diào)用WindowManagerImpl的addView()
具體是:
WindowManagerImpl.java
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
這個(gè)mGlobal是:
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
也就是WindowManagerImpl也沒(méi)有實(shí)權(quán),實(shí)權(quán)具體在mGlobal中:
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.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
在這里我們看到了
- root = new ViewRootImpl(view.getContext(), display);
- mViews.add(view);
- mRoots.add(root);
- mParams.add(wparams);
- root.setView(view, wparams, panelParentView);
生成ViewRoot對(duì)象,然后將這個(gè)View也就是到目前為止是DecorView設(shè)置到ViewRoot對(duì)象中。
所以下面才是正兒八經(jīng)剖析ViewRoot開(kāi)始
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
root = new ViewRootImpl(...)
Surface mSurface = new Surface()//成員變量
mWindowSession = WindowManagerGlobal.getWindowSession()
IWindowManager windowManager = getWindowManagerService()
sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"))
sWindowSession = windowManager.openSession()
Session session = new Session()//在WMS中
mWindow = new W(this)//構(gòu)造函數(shù)
ViewRootImpl的構(gòu)造
public ViewRootImpl(Context context, Display display) {
...
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();//Session
mWindow = new W(this);
...
}
核心在于這個(gè)W和Session這兩個(gè)都是Binder的實(shí)現(xiàn)類
- mWindowSession: 引用著WMS的Session對(duì)象
- mWindow是Binder實(shí)體類在ViewRootImpl中
最終形成的關(guān)系:
| APP | 引用變量 | WMS |
|---|---|---|
| WindowManagerGlobal | --IWindowSession--> | Session |
| W | <--IWindow-- | WindwState |
現(xiàn)在我們知道ViewRoot中存在兩個(gè)Binder類,一個(gè)Session代理,一個(gè)W實(shí)體。所以ViewRoot是和WMS通信的核心類
在ViewRoot中還有個(gè)核心方法requestLayout()
當(dāng)setView的時(shí)候調(diào)用requestLayout()這個(gè)方法進(jìn)行界面的繪制
ViewRootImpl.java
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
其中:
//將runnable發(fā)送給handler執(zhí)行
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
這句目的是將mTraversalRunnable發(fā)送給handler進(jìn)行處理
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
在這個(gè)函數(shù)中會(huì)調(diào)用測(cè)量布局繪制那些邏輯