如题所示,Activity是如何显示出来的呢?简单,调用startActivity就能够启动目标Activity了。很方便,但其实也隐藏了不少细节。startActivity后发生了什么事?怎么一个简单的接口就能启动一个界面,且该界面所在进程还未启动过。本篇文章承接《我是怎么把一个个App进程建立起来的》,描述接下来发生的事。java
想要启动一个Activity,首先得启动它的进程,由AMS将启动进程的需求发给Zygote,由这位大佬fork出一个进程,而后启动。启动的入口是ActivityThread类的main方法,分析从这里开始。android
咱们总说UI的刷新是在主线程进行的,但却没找到相关主线程的痕迹。今天它来了,UI主线程就在此处。这里列出main方法关键代码进行分析。微信
//frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
....
//①建立一个Loop实体,用于消息处理
Looper.prepareMainLooper();
....
//②建立ActivityThread对象,而后在attach方法中会完成Application对象的初始化,而后调用Application的onCreate()方法
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
//③获取Handler对象
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
....
④启动Loop,表示能够接收Handler发过来的消息
Looper.loop();
}
复制代码
如上按照注释,main方法中作的事情主要有三件,建立Loop实体,获取Handler,用于消息处理,建立ActivityThread对象,而后调用attach方法完成Application的初始化。咱们先看看attach方法作了什么事:app
//frameworks/base/core/java/android/app/ActivityThread.java
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
//启动JIT编译器,开始编译
ensureJitEnabled();
}
});
//设置进程名
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit.
//看app进程内存状况,若是太大则释放内存
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
//使用的内存超过最大内存的四分之三,则请求释放内存
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
} else {
....
}
....
}
复制代码
应用进程调用的attach方法传入的第一个参数为false,因此咱们这里主要看false分支的代码就行了。这里面主要作了以下几件事:框架
1.启动JIT编译器,开始编译; //这是啥,我也不清楚,后面再找时间补充学习
2.设置进程名;
3.经过ActivityManager获取AMS服务代理对象IActivityManager,经过它来完成一次跨进程操做,主要是用来绑定ApplicationThread对象;
4.内存使用检测,若发现使用的内存超过最大内存的四分之三,则申请进行内存释放;
复制代码
这里还看不出Activity的显示相关,还须要进入AMS进行查看attachApplication方法:ide
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
复制代码
这里又封装了一层,调用attachApplicationLocked方法:oop
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
....
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
....
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
....
}
复制代码
attachApplicationLocked方法比较长,在进行bind以前,前面部分在进行一些app的准备工做。一切准备就绪,会回调ActivityThread对象自己的bindApplication方法进行绑定。接着若是这个进程有待显示的Activity在栈顶,则会调用ActivityStackSupervisor类的attachApplicationLocked方法进行显示。post
/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
....
try {
if (realStartActivityLocked(activity, app,
top == activity /* andResume */, true /* checkConfig */)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ top.intent.getComponent().flattenToShortString(), e);
throw e;
}
....
}
复制代码
最终调用realStartActivityLocked方法:学习
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
r.appToken);
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, app.repProcState, r.icicle,
r.persistentState, results, newIntents, mService.isNextTransitionForward(),
profilerInfo));
...
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
...
}
复制代码
该方法建立了一个加载Activity的事务,等一切状态就绪,调用ClientLifecycleManager类的scheduleTransaction方法开始处理事务。ui
/frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
复制代码
最终调用了ClientTransaction对象的schedule方法,ClientTransaction对象在上个方法中被建立,即上述所说的事务。回到ClientTransaction的实现:
frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
复制代码
mClient又是什么?这是一个IApplicationThread类型的变量,该变量在建立事务的时候被赋值:
public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
if (instance == null) {
instance = new ClientTransaction();
}
instance.mClient = client;
instance.mActivityToken = activityToken;
return instance;
}
复制代码
兜兜转转,咱们须要返回realStartActivityLocked方法中查看client究竟是个啥:
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
r.appToken);
复制代码
建立启动Activity事务时,传入了一个IApplicationThread引用,这只是个代理,真正的实如今ApplicationThread类中,这是ActivityThread类的内部类,看看具体实现:
frameworks/base/core/java/android/app/ActivityThread.java
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
复制代码
这里直接调用ActivityThread父类的方法,发出一个处理事务的msg:
frameworks/base/core/java/android/app/ClientTransactionHandler.java
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
复制代码
具体处理仍是ActivityThread中:
public void handleMessage(Message msg) {
...
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
...
}
复制代码
还未到终点,又是一个execute方法,进入看看:
frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
final IBinder token = transaction.getActivityToken();
log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
log("End resolving transaction");
}
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
....
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
....
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
....
}
....
}
复制代码
这里若是直接进入到ClientTransactionItem类中,会发现并没有具体实现,这就是个抽象类。item是从事务中获取的回调,还记得在realStartActivityLocked方法中建立事务的过程么?建立了事务以后,还作了一件事:
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, app.repProcState, r.icicle,
r.persistentState, results, newIntents, mService.isNextTransitionForward(),
profilerInfo));
复制代码
这里增长了一个LaunchActivityItem类的回调,而LaunchActivityItem正是继承ClientTransactionItem类,因此这里的execute方法应该是在LaunchActivityItem类中实现:
frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
复制代码
又回调了ActivityThread(继承ClientTransactionHandler抽象类)的handleLaunchActivity方法:
frameworks/base/core/java/android/app/ActivityThread.java
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
....
final Activity a = performLaunchActivity(r, customIntent);
....
}
复制代码
真正启动Activity的核心即将到来:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
....
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
....
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, window, r.configCallback);
....
mInstrumentation.callActivityOnPostCreate(activity, r.state);
....
}
复制代码
这里主要作了三件事:
1.经过Instrumentation类建立出activity;
2.调用activity的attach方法建立窗口,为onCreate方法作准备;
3.经过callActivityOnPostCreate方法,最终调用activity的onCreate方法,在该方法中,经过setContentView方法将activity具体的view树加载到窗口。
复制代码
到了这里,Activity还未真正显示出来,只是该作的准备都作好了,下一步就是将具体的view加载到窗口中进行显示。这部份内容留到下一章节分析。
Activity的启动确实复杂,到如今也只是大概捋了个流程,并无深刻理解。在本章节中,大概分析了startActivity的流程。若是Activity所在进程是首次启动,则还须要经过AMS向Zygote进程发起进程建立的需求,而后在建立出来的子进程中,使用反射的方法,找到App的ActivityThread的main方法,并启动运行。
先掌握大概的流程框架,再逐步深刻了解各个模块。下一个章节分析view的加载。
我在微信公众号也有写文章,更新比较及时,有兴趣者能够扫描以下二维码,或者微信搜索【Android系统实战开发】,关注有惊喜哦!