Activity页面的绘制流程,中高级Android面试中你不得不会的知识点

final Activity a = r.activity;

boolean willBeVisible = !a.mStartedActivity;

if (!willBeVisible) {

try {

willBeVisible = ActivityManager.getService().willActivityBeVisible(

a.getActivityToken());

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

if (r.window == null && !a.mFinished && willBeVisible) {

r.window = r.activity.getWindow();

View decor = r.window.getDecorView();

decor.setVisibility(View.INVISIBLE);

2.获取WindowManagerImpl对象

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();

}

}

if (a.mVisibleFromClient) {

if (!a.mWindowAdded) {

a.mWindowAdded = true;

3.调用WindowManagerImpl的addView方法

wm.addView(decor, l);

}

}

}

}

1.我们先来看看注释1

跟一下它的源码,代码只贴主要流程的,有兴趣的朋友可以自己去查看详细的。

@VisibleForTesting

public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,

String reason) {

//省略部分代码

final ActivityClientRecord r = mActivities.get(token);

//省略部分代码

//调用Activity的performResume方法

r.activity.performResume(r.startsNotResumed, reason);

return r;

}

final void performResume(boolean followedByPause, String reason) {

//省略部分代码

//调用Instrumentation的callActivityOnResume方法

mInstrumentation.callActivityOnResume(this);

//省略部分代码

}

public void callActivityOnResume(Activity activity) {

activity.mResumed = true;

//调用Activity的onResume

activity.onResume();

if (mActivityMonitors != null) {

synchronized (mSync) {

final int N = mActivityMonitors.size();

for (int i=0; i<N; i++) {

final ActivityMonitor am = mActivityMonitors.get(i);

am.match(activity, activity, activity.getIntent());

}

}

}

}

上面我们跟了一下performResumeActivity的源码,发现最后调用了Activity的onResume,由此我们可以知道在注释一的时候,Activity的onResume方法其实已经执行完成了,但是我们的界面绘制还没有开始呢,印证了我们开头说的。

2.下面我们来看看注释2这个wm到底是个什么东西呢,看看它的具体实现类是什么。

//Activity的getWindowManager方法

public WindowManager getWindowManager() {

return mWindowManager;

}

//mWindowManager是在Activity的attach方法中被创建的

//这个方法是handleResumeActivity前执行的分析启动流程的时候我们会说到

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,

Window window) {

//调用setWindowManager方法

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());

}

//直接调用Window的getWindowManager方法

mWindowManager = mWindow.getWindowManager();

}

//Window的setWindowManager方法

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,

boolean hardwareAccelerated) {

if (wm == null) {

wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);

}

//调用WindowManagerImpl的createLocalWindowManager方法创建mWindowManager对象

mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);

}

//Window的getWindowManager方法

public WindowManager getWindowManager() {

return mWindowManager;

}

//WindowManagerImpl的createLocalWindowManager创建的是一个WindowManagerImpl对象

public WindowManagerImpl createLocalWindowManager(Window parentWindow) {

return new WindowManagerImpl(mContext, parentWindow);

}

根据以上源码我们知道了注释2的vm其实就是WindowManagerImpl对象。注释1注释2这两个前菜已经给大家分析完了。下面我们进入主题Activity页面的绘制。

- (2)WindowManagerImpl.addView

通过前面的分析,我们可以知道注释3处其实就是调用了WindowManagerImpl的addView方法。下面我们来看看这个方法到底做了什么。

@Override

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {

applyDefaultToken(params);

//调用WindowManagerGlobal的addView方法

mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);

}

//WindowManagerGlobal的addView

public void addView(View view, ViewGroup.LayoutParams params,

Display display, Window parentWindow) {

ViewRootImpl root;

View panelParentView = null;

1.创建ViewRootImpl对象

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 {

2.调用ViewRootImpl的setView方法

root.setView(view, wparams, panelParentView);

} catch (RuntimeException e) {

// BadTokenException or InvalidDisplayException, clean up.

if (index >= 0) {

removeViewLocked(index, true);

}

throw e;

}

}

}

注释1是个很重要的点,这里创建了一个ViewRootImpl对象。

我们来解析一下这个ViewRootImpl里面需要关注的几个点。

我们先看看ViewRootImpl的构方法:

public ViewRootImpl(Context context, Display display) {

//获取Session对象

mWindowSession = WindowManagerGlobal.getWindowSession();

mDisplay = display;

mBasePackageName = context.getBasePackageName();

//主线程

mThread = Thread.currentThread();

//创建Choreographer对象,这个对象很重要,可以把它理解为一个Handler

//Android 16.6ms刷新一次页面它启到了主要作用

//我们马上看看这个Choreographer是个什么

mChoreographer = Choreographer.getInstance();

mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

}

ViewRootImpl的构造方法里面我们暂时值关注两件事

1.获取了Session对象这个对象是我们与WindowManagerService交互的桥梁。

2.创建了Choreographer对象。

我们现来看看这个Choreographer对象到底是什么,为什么它那么重要呢?

public static Choreographer getInstance() {

return sThreadInstance.get();

}

// Thread local storage for the choreographer.

private static final ThreadLocal sThreadInstance =

new ThreadLocal() {

@Override

protected Choreographer initialValue() {

//注意了这里其实就是主线程的Looper

//ViewRootImpl对象就是在主线程创建的

Looper looper = Looper.myLooper();

if (looper == null) {

throw new IllegalStateException(“The current thread must have a looper!”);

}

//创建Choreographer对象

Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);

if (looper == Looper.getMainLooper()) {

mMainInstance = choreographer;

}

return choreographer;

}

};

private Choreographer(Looper looper, int vsyncSource) {

mLooper = looper;

//前面我们说了正常情况瞎这个looper对象就是主线程的looper对象

//所以通过这个Handler发送的消息都是在主线程处理的

mHandler = new FrameHandler(looper);

//创建FrameDisplayEventReceiver

//这个对象可以理解为一个任务

mDisplayEventReceiver = USE_VSYNC

? new FrameDisplayEventReceiver(looper, vsyncSource)
null;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后

我坚信,坚持学习,每天进步一点,滴水穿石,我们离成功都很近!
以下是总结出来的字节经典面试题目,包含:计算机网络,Kotlin,数据结构与算法,Framework源码,微信小程序,NDK音视频开发,计算机网络等。

字节高级Android经典面试题和答案


)]
[外链图片转存中…(img-KO3oaAQI-1711724737737)]
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-wbGNGqcD-1711724737738)]

最后

我坚信,坚持学习,每天进步一点,滴水穿石,我们离成功都很近!
以下是总结出来的字节经典面试题目,包含:计算机网络,Kotlin,数据结构与算法,Framework源码,微信小程序,NDK音视频开发,计算机网络等。

字节高级Android经典面试题和答案

[外链图片转存中…(img-u65zGEDz-1711724737738)]
[外链图片转存中…(img-zL0hTaf5-1711724737738)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值