简介
我们知道在Android系统中Activity代表一个窗口的显示,甚至初学者认为Activity就是一个显示窗口,在Activity中能够完成显示的所有功能,但是这样理解有偏差,Activity之所以能承载显示是由于内部存在很多与显示相关的核心类,Activity只是通过一些管理方法和回调函去处理这些核心类的核心方法。所以我们应该更深层次的接触Activity。
由于笔者之前接触界面开发很少,甚至没有怎么接触界面开发,所以对Activity的源码也不懂,我也是抱着学习的心态,去尝试研究Activity与显示的关系,所以有什么不对或者需要笔者完善的地方希望读者能够提出来,只有提出问题,我才能去主动探求答案找寻真理。更好的分享给大家,达到共同学习共同进步的目的。好了话不多少进入今天的主题。
源码分析
关于Activity的启动流程并不是今天的重点,所以我大概提下Activity的启动过程,我们重点在于后面
我们之前分析过APP进程启动的过程会启动Activity,我们就从进程启动后进入Activity启动流程分析
AMS.startProcessLocked
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
...
////只有当系统启动完,或者app允许启动过程允许,则会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;
}
//获取前台stack中栈顶第一个非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 {
//真正的启动Activity
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
throw e;
}
}
}
}
}
if (!didSomething) {
//启动Activity不成功,则确保有可见的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;
//最终回调目标Activity的onConfigurationChanged()
handleConfigurationChanged(null, null);
//初始化wms
WindowManagerGlobal.initialize();
//最终回调目标Activity的onCreate
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//最终回调目标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);
}
}
我们现在涉及到了两个关键点
- 现在
Activity a = performLaunchActivity(r, customIntent);
Activity生产出来了 - 最终调用handleResumeActivity()目前也看不出这个方法干啥
我们就针对这两个核心调用进行分析
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 {
//创建Application对象
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;
}
我们通过这段代码可以看出来
- 根据类名使用反射创建一个Activity实例化对象
- 调用Activity的onCreate方法
我们结合上面可以知道是在主线程中执行,所以Activity.onCreate()方法是在主线程中调用的,一般情况下我们会在onCreate()方法中使用setContentView()进行设置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);
}
...
}
这里有几个重点:
- r.window = r.activity.getWindow()出现了window
- View decor = r.window.getDecorView()出现了view
- ViewManager wm = a.getWindowManager()出现了ViewManager
这部分和UI有关,但是我们在这块并不知道哪里来的这些变量,突然就冒出来让我们有点不知所措。所以我们回想一下,刚才调用了onCreate()之后才发生这些的,onCreate()是不是我们要调用setContentView设置一些什么东东呢哈哈。
setContentView()
Activity.java
private Window mWindow;
public void setContentView(View view) {
getWindow().setContentView(view);
initWindowDecorActionBar();
}
public Window getWindow() {
return mWindow;
}
mWindow是什么,在哪里创建的?
那么我们就只能在Activity创建的过程中寻找答案.
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)...);
所以这个时候我们明白在Activity中mWindow是PhoneWindow对象,并且mWindow设置了名称为window的服务
我们继续回到setContentView的这个话题,我们现在知道是调用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();
}
}
调用了两个核心:
- 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();
//此时的layoutResource代表整个界面
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);
}
代码可以看出来,我们先加载View然后添加到decor中,对于这个contentid也只不多是DecorView的一部分。
所以我们通过包含关系形容他们
PhoneWindow
DecorView
MyView
我们在通过文字来描述一下这个关系
我们在Activity通过反射创建之后会调用Activity.attach()方法在这个方法中会创建PhoneWindow和对PhoneWindow设置名称是window的服务,当我们在Activity.onCreate()方法中使用setContentView的时候会创建DecorView,然后将整个一些元素添加到DecorView中
所以我们在Activity中的那些界面其实最根部的设置是由DecorView这个View保存设置的。
目前为止我们通过:
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);
}
...
}
这个方法得知,现在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
我们在attach方法中进行创建
final void attach(...) {
attachBaseContext(context);
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
...);
...
mWindowManager = mWindow.getWindowManager();
}
我们知道mWindow是PhoneWindow对象,在其父类Window中实现了getWindowManager方法:
public WindowManager getWindowManager() {
return mWindowManager;
}
同样在PhoneWindow的父类Window中构造并且设置了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);
}
到这里我们就知道对应ViewManager是WindowManagerImpl对象
也就是说我们在Activity.attach()中创建了WindowManagerImpl对象然后在handleResumeActivity方法中利用WindowManagerImpl将产生的decorView添加到wm中。
在小结:
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)//构造函数
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)//将这个window加入列表中
requestLayout()
scheduleTraversals()
run(){doTraversal()}
performTraversals()
我们在app进程启动的时候会初始android环境,然后过程中会启动activity,在启动activity的时候是通过反射方法生成Activity对象调用attach之后然后会调用Activity的OnCreate()方法在调用attach过程中会生成一些核心的对象其中主要有PhoneWindow对象与WindowManagerImpl对象,当调用onCreate()的时候会使用setContentView做设置布局,这个时候就会产生mDecor(DecorView)最后执行到handleResumeActivity这个方法也就是对应Activity声明周期回调的OnResume方法,此时将DecorView对象添加到WindowManagerImpl中进行管理。
后面大概的内容还有个ViewRoot,Surface,WMS,RawBuffer等等。因为我们到目前为止知道DecorView是根布局,但是我们并牵扯到绘制,按键监听消息通信方面的知识所以我们以后的分析会更难,因为牵扯到通信模块与WMS的管理模块了,不要灰心一点点看总会进步。
ViewRoot剖析
为什么我们要剖析ViewRoot呢?到目前为止我们发现我们并没有与任何绘制有关的进程进行通信所以我们需要继续剖析Android系统如何进行绘制管理的。所以ViewRoot是与WMS,Surface打交道的枢纽。
我们在ActivityThread.handleResumActivity()的时候会有如下代码:
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);
}
....
}
}
在这里面调用ViewManager的add方法,但是是谁实现了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);
}
注意了主角来了:
也就是说我们上面:
ActivityThread.handleResumActivity(){
...
wm.addView(decor, l);
...
}
是调用WindowManagerImpl的addView()
具体是:
WindowManagerImpl.java
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
这个mGlobal是:
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
也就是WindowManagerImpl也没有实权,实权具体在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对象,然后将这个View也就是到目前为止是DecorView设置到ViewRoot对象中。
所以下面才是正儿八经剖析ViewRoot开始
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)//构造函数
ViewRootImpl的构造
public ViewRootImpl(Context context, Display display) {
...
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();//Session
mWindow = new W(this);
...
}
核心在于这个W和Session这两个都是Binder的实现类
- mWindowSession: 引用着WMS的Session对象
- mWindow是Binder实体类在ViewRootImpl中
最终形成的关系:
APP | 引用变量 | WMS |
---|---|---|
WindowManagerGlobal | --IWindowSession--> | Session |
W | <--IWindow-- | WindwState |
现在我们知道ViewRoot中存在两个Binder类,一个Session代理,一个W实体。所以ViewRoot是和WMS通信的核心类
在ViewRoot中还有个核心方法requestLayout()
当setView的时候调用requestLayout()这个方法进行界面的绘制
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发送给handler执行
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
这句目的是将mTraversalRunnable发送给handler进行处理
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;
}
}
}
在这个函数中会调用测量布局绘制那些逻辑