Activity代码很简单,调用getWindow().setContentView(layoutResID),即调用了PhoneWindow的setContent()方法
贴一下PhoneWindow的setContent方法bash
@Override
public void setContentView(int layoutResID) {
//安装DecorView
if (mContentParent == null) {
installDecor();
}
// ·······省略部分代码·······
//将设置的layoutResID的布局放入到 mContentParent中
mLayoutInflater.inflate(layoutResID, mContentParent);
// ·······省略部分代码·······
}
复制代码
关键方法installDecoride
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
//1.构建DecorView
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
//2.生成mContentParent mContentParent实际是id为ID_ANDROID_CONTENT的FrameLayout,即要添加布局的父布局。
mContentParent = generateLayout(mDecor);
final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent);
//3.设置Activity标题栏相关
if (decorContentParent != null) {
mDecorContentParent = decorContentParent;
mDecorContentParent.setWindowCallback(getCallback());
if (mDecorContentParent.getTitle() == null) {
mDecorContentParent.setWindowTitle(mTitle);
}
final int localFeatures = getLocalFeatures();
for (int i = 0; i < FEATURE_MAX; i++) {
if ((localFeatures & (1 << i)) != 0) {
mDecorContentParent.initFeature(i);
}
}
mDecorContentParent.setUiOptions(mUiOptions);
if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
(mIconRes != 0 && !mDecorContentParent.hasIcon())) {
mDecorContentParent.setIcon(mIconRes);
} else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
mIconRes == 0 && !mDecorContentParent.hasIcon()) {
mDecorContentParent.setIcon(
getContext().getPackageManager().getDefaultActivityIcon());
mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
}
if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
(mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
mDecorContentParent.setLogo(mLogoRes);
}
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else {
mTitleView = findViewById(R.id.title);
if (mTitleView != null) {
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
final View titleContainer = findViewById(R.id.title_container);
if (titleContainer != null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
}
mContentParent.setForeground(null);
} else {
mTitleView.setText(mTitle);
}
}
}
//4.设置背景
if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
mDecor.setBackgroundFallback(mBackgroundFallbackResource);
}
// 5.获取过渡元素相关信息
if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
// ·······省略部分代码·······
}
}
}
复制代码
installDecor()主要有四个部分oop
至此,DecoverView构建完成,并将布局添加入DecoverView中布局
咱们知道,在Activity生命周期,onStart方法在视图可见时触发,那么DecoverView添加到window确定在onStart方法以前
咱们一步一步往前找会发现
Activity.onStart <- Instrumentation.callActivityOnStart <- Activity.performStart <- Activity.performRestart <- Activity.performResume <- ActivityThread.performResumeActivity <- ActivityThread.handleResumeActivity
咱们从handleResumeActivity分析post
(有兴趣的能够继续向前查找 Activity.startActivityForResult -> Instrumentation.execStartActivity -> ActivityManagerService.startActivity -> ActivityManagerService.startActivityAsUser -> ActivityStarter.execute -> ActivityStarter.startActivity -> ActivityStarter.startActivityUnchecked-> ActivityStack.ensureActivitiesVisibleLocked -> ActivityStack.makeVisibleAndRestartIfNeeded -> ActivityStackSupervisor.startSpecificActivityLocked -> ActivityStackSupervisor.realStartActivityLocked -> ClientLifecycleManager.scheduleTransaction -> ApplicationThread.scheduleTransaction -> ActivityThread.scheduleTransaction -> Activity.sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction) -> ActivityThread.H.handleMessage case:EXECUTE_TRANSACTION -> TransactionExecutor.execute -> TransactionExecutor.executeLifecycleState -> ResumeActivityItem.execute -> ActivityThread.handleResumeActivity )
动画
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// 取消空闲状态的 GC任务
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// 1.执行Activity的resume方法
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
// ·······省略部分代码·······
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
// 2.将decorView设置为INVISIBLE
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 (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
//3. 将decor添加到WindowManager中
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
// ·······省略部分代码·······
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
// ·······省略部分代码·······
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
//4. 设置Activity可见
r.activity.makeVisible();
}
}
r.nextIdle = mNewActivities;
mNewActivities = r;
// 添加空闲任务
Looper.myQueue().addIdleHandler(new Idler());
}
复制代码
主要包含三部分ui
wm.addView的方法实如今WindowManagerImpl中,而后又调用了代理类WindowManagerGlobal的addView方法,下面看下WindowManagerGlobal.addView方法this
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
// ·······省略部分代码·······
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
//1. 添加系统属性更改回调,发送变化时,调用ViewRootImpl的loadSystemProperties方法
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);
}
//2.判断该view是否已被添加,若是被添加过,而且在正在销毁的列表中,则进行销毁,不然抛出非法状态异常
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
}
// ·······省略部分代码·······
//3.建立ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// 4.调用ViewRootImpl的setView方法
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
复制代码
主要有四步:spa
从ViewParent注释能够看出,视图的顶部,协调View和WindowManager,不少程度上实现了WindowManagerGlobal的细节。
咱们从setView开始看线程
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
//向DisplayManager注册显示屏监听器 能够监听到显示屏的打开和关闭
mAttachInfo.mDisplayState = mDisplay.getState();
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
// 手机反馈事件处理
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
// ·······省略部分代码·······
//建立mSurfaceHolder
if (view instanceof RootViewSurfaceTaker) {
mSurfaceHolderCallback =
((RootViewSurfaceTaker)view).willYouTakeTheSurface();
if (mSurfaceHolderCallback != null) {
mSurfaceHolder = new TakenSurfaceHolder();
mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
mSurfaceHolder.addCallback(mSurfaceHolderCallback);
}
}
// ·······省略部分代码·······
// 1. 在添加到windowManager以前 安排一次布局 ,以确保咱们在从系统接收任何其余事件以前进行从新布局。
requestLayout();
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
mInputChannel = new InputChannel();
}
mForceDecorViewVisibility = (mWindowAttributes.privateFlags
& PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
// 2.经过IPC将window添加入WindowSeession进行显示
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
}
// ·······省略部分代码·······
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
// 3. 建立窗口输入事件接收器,并设置输入管道流
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
// 4. 将ViewRootImpl绑定为DecorView的Parent
view.assignParent(this);
// ·······省略部分代码·······
// 5. 经过责任链模式处理输入阶段 主要针对触摸事件和物理按键事件
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
}
}
}
复制代码
把代码主要分为了五步
看下requestLayout方法
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
复制代码
代码很简单,检查线程,执行scheduleTraversals 检查线程会判断当前线程是否为UI线程,若是不是UI线程,则抛出异常,这里就是为何子线程不能更新UI的缘由。
可是子线程真的不能更新UI吗?从上面分析咱们能够看出,当在wm.addView时,才会建立的ViewRootImpl,而wm.addView,是在onResume时执行,因此若是在onResume执行前,是能够在子线程更新UI。(其实这个时候视图并无被添加到view中)
接下来看下scheduleTraversals方法
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 1.在MessageQueue中添加同步栅栏
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 2.由编舞者处理 布局和绘制
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
// 3.通知渲染层将有新的帧
notifyRendererOfFramePending();
// 若是须要释放绘制锁
pokeDrawLockIfNeeded();
}
}
复制代码
mChoreographer.postCallback方法的内部的调用链
postCallback -> postCallbackDelayed -> postCallbackDelayedInternal -> scheduleFrameLocked -> doFrame(System.nanoTime(), 0) -> doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos)
最终会调用上一部传入的mTraversalRunnable的run方法 mTraversalRunnable.run -> doTraversal -> performTraversals performTraversals方法是主要的绘制方法。performTraversals会依次执行 performMeasure -> performLayout -> performDraw 完成视图的帧绘制