Android高工面:Activity创建到View呈现中间发生了什么?子线程到底能不能更新UI

本文详细解释了Android应用程序启动过程中Activity的创建、Context关联、Window管理、setContentView以及handleResumeActivity方法的执行步骤,包括WindowManagerImpl的addView方法,帮助理解Android应用生命周期管理的关键环节。
摘要由CSDN通过智能技术生成

//创建Activity
Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

if (activity != null) {
//创建Context
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);

//调用Activity.attach。
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);

//省略代码…

//调用Activity.onCreate()方法。
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.activity = activity;

if (!r.activity.mFinished) {
//调用Activity.onStart()方法。
activity.performStart();
}
}
r.paused = true;
mActivities.put(r.token, r);
return activity;
}

performLaunchActivity()主要做了以下几件事:

  1. 创建Activity。
  2. 创建Context。
  3. 调用Activity.attach(),创建Window,关联WindowManager。
  4. 调用Activity.onCreate()。
  5. 调用Activity.onStart()。

attach

上面说了,在Activity.attach()方法执行时会创建Window并为Window关联WindowManager。我们看一下伪代码。

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);
//创建Window
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);
}
//设置UI线程
mUiThread = Thread.currentThread();
mMainThread = aThread;
//关联WindowManager
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();
}

setContentView

顺着流程图,Activity.setContentView()方法会被调用。Activity.setContentView()内又直接调用了PhoneWindow.setContentView()。我们直接看PhoneWindow.setContentView()的源码。

private DecorView mDecor;

//setContentView传过来的View会被add到mContentParent中。mContentParent的Id是R.id.content。
private ViewGroup mContentParent;

@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if (mContentParent == null) {
installDecor();
}else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
//省略代码。。。
}

private void installDecor() {
if (mDecor == null) {
//初始化DecorView
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
//省略代码。。。
}
}

如果mContentParent为null,会执行installDecor()方法。generateDecor()源代码很长,但是它的逻辑很简单主要是根据Activity Theme的不同,初始化不同的布局。DecorView的布局虽然不同,但它们都一个Id为R.id.content的FrameLayout。Activity.setContentView()就是在这个FrameLayout中添加子View。

handleResumeActivity

performLaunchActivity()执行完后,紧接着执行handleResumeActivity()。

final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {

//处理Activity的onRestart onResume生命周期。
ActivityClientRecord r = performResumeActivity(token, clearHide);

if (r != null) {
if (r.window == null && !a.mFinished) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
//设置DecorView不可见
decor.setVisibility(View.INVISIBLE);

ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();

if (a.mVisibleFromClient) {
a.mWindowAdded = true;
//利用WindowManager添加DecorView。
wm.addView(decor, l);
}
}
if (!r.activity.mFinished && r.activity.mDecor != null) {
if (r.activity.mVisibleFromClient) {
//设置DecorView可见。
r.activity.makeVisible();
}
}

//IPC调用,通知AMS Activity启动完成。
ActivityManagerNative.getDefault().activityResumed(token);

} else {
try {
ActivityManagerNative.getDefault()
.finishActivity(token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
}
}
}

handleResumeActivity()处理的事情比较多。我总结为以下几个过程:

  1. 通过performResumeActivity()处理Activity的onRestart onResume的生命周期。
  2. 将DecorView设置为InVisible。
  3. 通过WindowManager.addView()将DecorView绘制完成。
  4. 将DecorView设置为Visiable。
  5. 通知AMS Activity启动完成。

WindowManger.addView()

前面说过,WindowManger是一个抽象类,它的实现类是WindowManagerImpl。WindowManager.addView()封装了View绘制的细节。我们着重看一下。

public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
private final Display mDisplay;
private final Window mParentWindow;

private IBinder mDefaultToken;

public WindowManagerImpl(Display display) {
this(display, null);
}

private WindowManagerImpl(Display display, Window parentWindow) {
mDisplay = display;
mParentWindow = parentWindow;
}

public void setDefaultToken(IBinder token) {
mDefaultToken = token;
}

@Override
//这里的View是PhoneWindow内创建的DecorView。
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}

private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {
if (mDefaultToken != null && mParentWindow == null) {
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (wparams.token == null) {
wparams.token = mDefaultToken;
}
}
}
}

WindowManagerImpl.addView会调用WindowManagerGlobal.addView()。在WindowManagerGlobal.addView()方法执行之前,会先执行applyDefaultToken()方法。这个方法其实是给传进来的DecorView加一个身份标识,表示这个DecorView属于哪个Activity。这样系统(WindowManagerService)才会知道要把DecorView绘制到哪个Activity。

我们继续追踪WindowManagerGlobal.addView(),伪代码如下:

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

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

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

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

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

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

最后

总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;

技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关

在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

相信自己,没有做不到的,只有想不到的

ndroid开发面试专题资料,高级进阶架构资料**这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

[外链图片转存中…(img-63ybrFol-1711742545915)]

[外链图片转存中…(img-Oi4VeOiH-1711742545916)]

相信自己,没有做不到的,只有想不到的

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值