脚本宝典收集整理的这篇文章主要介绍了Android View的绘制流程,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
Android 30 更新时间:2021-12-18
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) {
// Activity对象持有者
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
// 获取到Activity
final Activity a = r.activity;
// 获取到PhoneWindow
r.window = r.activity.getWindow();
// 获取到DecorView
View decor = r.window.getDecorView();
// 设置DecorView不可见
decor.setVisibility(View.INVISIBLE);
// 获取到WindowManager
ViewManager wm = a.getWindowManager();
// 获取到PhoneWindow的布局属性
WindowManager.LayoutParams l = r.window.getAttributes();
// 将 DecorView 添加到 ViewManager
wm.addView(decor, l);
}
来看下 performResumeActivity() 方法里面的内容: 里面调用了Activity的performResume方法
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest, String reason) {
final ActivityClientRecord r = mActivities.get(token);
r.activity.performResume(r.startsNotResumed, reason);
}
再看下 r.activity.performResume(r.startsNotResumed, reason); 的内容: 这里又调用了 callActivityOnResume方法
final void performResume(boolean followedByPause, String reason) {
mInstrumentation.callActivityOnResume(this);
}
再往 mInstrumentation.callActivityOnResume(this); 看: 最后会调用 onResume() 方法
public void callActivityOnResume(Activity activity) {
activity.onResume();
}
ViewManager wm = a.getWindowManager(); ViewManager 是一个接口,WindowManager 会继承它
public interface ViewManager {
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
WindowManager 继承 ViewManager,通过getWindowManager方法,返回了mWindowManager,那 mWindowManager在哪赋值的呢?
public WindowManager getWindowManager() {
return mWindowManager;
}
mWindowManager 会在 attach中进行赋值,这里调用的是mWindow.getWindowManager() ,再往里面看
final void attach(...) {
// 创建 PhoneWindow 对象
mWindow = new PhoneWindow(this, window, activityConfigCallback);
// 获取 WindowManager
mWindowManager = mWindow.getWindowManager();
}
会返回 mWindowManager,再去看 它是什么时候被赋值的
public WindowManager getWindowManager() {
return mWindowManager;
}
mWindowManager 在什么时候被赋值的呢,是在 setWindowManager 方法中,从 WindowManagerImpl拿到的;
另外,WindowManagerImpl 是 WindowManager 的实现类;
ViewManager wm = a.getWindowManager(); 是 从 WindowManagerImpl 拿到的;
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated;
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
wm 为 ViewManager; WindowManager 继承 ViewManager; WindowManagerImpl 是 WindowManager 的实现类;
那 wm.addView(decor, l); 也就是 调用的 WindowManagerImpl 的 addView方法;
来看下 WindowManagerImpl 的 addView 方法: 是调用了 WindowManagerGlobal 的 addView 方法
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
// WindowManagerGlobal mGlobal
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
WindowManagerGlobal 是管理整个进程,所有的窗口信息的; 看下它的 addView方法内容
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow, int userId) {
ViewRootImpl root;
// 创建 ViewRootImpl 对象
root = new ViewRootImpl(view.getContext(), display);
mViews.add(view); // DecorView
mRoots.add(root); // ViewRoomImpl
mParams.add(wparams); // WindowManager.LayoutParams
// DecorView 和 ViewRootImpl 关联
root.setView(view, wparams, panelParentView, userId);
}
ViewRootImpl 是 操作自己的窗口
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
mView = view;
// 请求遍历
requestLayout();
// 将窗口添加到 WindowManagerService 上
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
view.assignParent(this);
}
进行请求遍历操作
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread(); // 线程检查
mLayoutRequested = true;
scheduleTraversals(); // 主要看这个
}
}
// 检查当前线程
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
public ViewRootImpl(Context context, Display display, IWindowSession session, boolean useSfChoreographer) {
mThread = Thread.currentThread();
}
在 scheduleTraversals 中得 postCallback中有一个mTraversalRunnable,可以看到它最终调用 doTraversal 方法;
@UnsupportedAppUsage
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 看这个 mTraversalRunnable
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
performTraversals 是 绘制开始的地方
void doTraversal() {
performTraversals();
}
在 performTraversals 中,会进行预测量,测量,布局,绘制等操作;
private void performTraversals() {
boolean windowSizeMayChange = false;
// 预测量
windowSizeMayChange |= measureHierarchy(host, lp, res, desiredWindowWidth, desiredWindowHeight);
// 布局窗口
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
// 测量
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
// 布局
performLayout(lp, mWidth, mHeight);
// 绘制
performDraw();
}
预测量,会进行三次
private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp,
final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) {
boolean goodMeasure = false;
if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
res.getValue(com.android.internal.R.dimen.config_prefDialogWidth, mTmpValue, true);
if (baseSize != 0 && desiredWindowWidth > baseSize) {
childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
// 第一次测量
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
goodMeasure = true;
} else {
// 第二次测量
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
if ((host.getMeasuredWidthAndState()&View.MEASURED_STATE_TOO_SMALL) == 0) {
if (DEBUG_DIALOG) Log.v(mTag, "Good!");
goodMeasure = true;
}
}
}
}
if (!goodMeasure) {
childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
// 第三次测量
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) {
windowSizeMayChange = true;
}
}
}
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
if (mView == null) {
return;
}
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
try {
// 测量
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
onMeasure(widthMeasureSpec, heightMeasureSpec);
}
// 当自己重写 onMeasure 的时候,需要调用setMeasuredDimension,否则会抛出异常
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth, int desiredWindowHeight) {
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
}
private void performDraw() {
boolean canUseAsync = draw(fullRedrawNeeded);
}
Android setContentView流程:https://blog.csdn.net/yan13507001470/article/details/121588583
请多指教。
以上是脚本宝典为你收集整理的Android View的绘制流程全部内容,希望文章能够帮你解决Android View的绘制流程所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。