果然人在家里就比较容易犯懒,差点又被自己说服去睡觉了。——10.2
被ActivityTaskManagerService玩惨了——10.3
前言
前面已经梳理了一下,我们的布局文件layout
是如何加载的,原材料已经有了,现在就可以总结一下我们耳熟能详的measure
、layout
、draw
了。
结果今天看了两篇博客之后,发现事情并没有这么简单,好像少了点什么??
嗯...我们把整个事情的整个流程捋一下:
首先,我们把自定义layout
加载到DecorView
;
然后,我们按照measure
、layout
、draw
流程来绘制View
......
嗯...
不对啊!DecorView
是在哪显示的,又是在哪调用的绘制View
......
......
我的Activity
呢???我的Window
呢??我这么大一个组件怎么就没了?!
所以,只能含着泪在标题上加上了“前一章”的字样(看来不能好好睡觉了),只能先来看看:
-
Activity
的启动过程; -
Activity
和Window
又是怎么来衔接DecorView
的加载和绘制的;
源码
Activity启动分析
回归到一个刚刚接触到Android
的萌新状态(虽然现在也是萌新),如果说需要显示或者说修改UI,第一件事就是打开Activity
。众所周知,Activity
是一种用于直接向用户展示界面的组件。OK,那我们从Activity开始入手,一步一步看一下他是如何展示界面的。
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
这就是我们可以见到的Activity
的起点,代码非常简单,直接调用Activity.startActivity()
。
继续向下看startActivity()
经过几次重载,最终调用了startActivityForResult()
。
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
//1.对options进行封装,options为null就采用系统默认,不为空则直接使用
options = transferSpringboardActivityOptions(options);
//2.生成ActivityResult对象,里面包含resultCode和resultData
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
//3.执行发送消息ActivityResult
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
//取消输入功能和动画的执行
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
//通过mParent创建,创建过程与上方代码类似
}
}
看了一下刚哥的《开发艺术探索》这里的mParent
是用来针对镶嵌子Activity
的场景的,这里只需要看mParent == null
.(正好我们只是想看一下启动和绘制的关系,这里就不纠结了),大致流程如下:
- 对
options
进行封装,options
为null
就采用系统默认,不为null
则直接使用; - 生成
ActivityResult
对象,里面包含resultCode
和resultData
; - 执行发送消息
ActivityResult
; - 取消输入功能和动画的执行;
这里可以看到在第三步中已经开始发送ActivityResult
,那Activity
的启动应该就在第二步中的Instrumentation.execStartActivity()
,我们跟进去看代码;
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
//1.存储`startActivity()`发起者的信息
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
//2.测试相关判定
if (mActivityMonitors != null) {
//ActivityMonitor类是Google为了InstrumentationTest而加入的一个工具类,这里不关注
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//3.启动Activity的核心
int result = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//4.用于检查打开Activity异常的方法,我们常见的Activity启动异常都在这里
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
大致流程如下:
- .存储
startActivity()
发起者的信息; - 测试相关判定;
- 启动Activity的核心;
- 用于检查打开Activity异常的方法,我们常见的Activity启动异常都在这里;
说实话,看到这里,我多少是有点小激动的,毕竟看起来,马上就可以揭晓谜底了,但是现实告诉我:"你高兴的太早了!",点进去看一下启动Activity的核心:
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
直接看代码的最后一行,出现了关键句IActivityTaskManager.Stub.asInterface(b)
这里使用Binder
的进程间通信,但是IActivityTaskManager
是什么东西?,不应该是IActivityManager
吗?然后转到ActivityManagerService
中?我太难了!!!
但是,不能气馁,我们先看一下ActivityManagerService
的代码,虽然代码有变化,但是基本结构应该不会有非常大的变化。
于是我找到了这个:
public ActivityTaskManagerService mActivityTaskManager;
看一下ActivityTaskManagerService
的源码:
public class ActivityTaskManagerService extends IActivityTaskManager.Stub
哈哈,功夫不负有心人,应该就是这里了,我们找一下startActivity()
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
之后就开始了N多的跳转最终来到了ClientLifecycleManager.class
,在这里通过ClientTransaction.class
和ClientTransactionItem
对Activity的加载和生命周期进行控制,这里只是加载,看代码:
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
这里关键是使用了LaunchActivityItem
和ResumeActivityItem
(也有用PauseActivityItem
)分布对应Activity中对应的生命周期:onCreate()
,onResume
,onPause
;
然后通过ActivityThread
、ApplicationThread
、H
对Activity
进行控制,调用ActivityThread
中的handleLaunchActivity
和handleResumeActivity
,具体流程如图:
DecorView绘制的调用
上面Activity启动的流程图的最后一步(第50步)没有仔细的绘制,接下来的部分会对这一部分进行详解,这里也就是DecorView
绘制的调用。
看代码,这里只保留绘制相关部分:
<ActivityThread.java>
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
......
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 (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
}
......
}
这里通过Activity
获取到ViewManager
,然后通过 使用ViewManager.addView()
将Window
和View
进行关联。
通过Activity
获取到的ViewManager
的本质是一个WindowManagerImp
,看一下WindowManagerImp.addView()
的代码:
<WindowManagerImp.java>
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
这里并没有进行比较哦多的操作,而是直接调用了mGlobal.addView
.(代码部分删减):
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
ViewRootImpl root;
View panelParentView = null;
//创建一个ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
// do this last because it fires off messages to start doing things
root.setView(view, wparams, panelParentView);
}
这里继续看root.setView(view, wparams, panelParentView)
,进入到了ViewRootImpl
,这里也是主要的View绘制过程的调用,经过几次调用,最终:
<ViewRootImpl.java>
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
在主线程中,使用TraversalRunnable
开始绘制,整体流程如下:
总结
1.Android Q 中Activity的启动,不再使用ActivityManagerService
,替换为ActivityTaskManagerService
;
2.UI在onCreate
中进行自定义布局的设置,在handleResumeActivity
完成UI绘制;
3.Window 与 WindowManager 之间的桥接模式,依赖关系存在于抽象类间,与实现&行为完全隔离
网友评论