关于Activity需要知道的更多内容
前言
Activity作为作为四大组件中我们最常见的一个组件,经常接触使用,但是往往每次让我们对这个组件进行说明的时候,我们只知道它的几个生命周期,几种启动模式,但是具体的更多的就讲不出来了。
ps:我在写这个之前实际上也是一知半解,所以今天我们一起去看看Activity更多的东西,源码版本为 android-26
- 1、Application的创建
- 2、Activity的创建和生命周期
一、Application的创建
我们知道,java程序想运行都是通过调用main方法来启动,我们的Android应用程序也是如此,但是我们每次都是直接点击手机屏幕的应用图标就直接启动了app,这时候难免有疑惑,我们为什么不需要调用main方法就可以直接启动我们的程序呢,虽然我们没有直接的去写main方法,但是实际上还是通过ActivityThread类的main方法来作为我们应用程序的入口。
# ActivityThread类
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();//1、这边new了一个ActivityThread对象
thread.attach(false);//2、这边去进行连接,连接什么?
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在ActivityThread类中,能看到一个main方法,它就是我们程序的入口,在注释1的地方,会去创建一个ActivityThread对象,在注释2的地方,调用thread的attach方法去连接,具体的连接什么我们继续看下面的代码
#ActivityThread类
private void attach(boolean system) {
...
if (!system) {
...
final IActivityManager mgr = ActivityManager.getService();//1、通过AIDL,获取AMS的代理对象IActivityManager
try {
mgr.attachApplication(mAppThread);//2、这边将AMS和我们的应用进程application进行连接
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
...
}
}
关于AIDL,这边不进行展开,我们关心的是注释2,这边通过AIDL将AMS和我们应用进程application进行连接,具体的是调用ActivityManagerService的attachApplication方法进行连接。
#ActivityManagerService类
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();//1、获取pid
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);//2、传入pid进行连接
Binder.restoreCallingIdentity(origId);
}
}
这边的注释1通过Binder对象获取应用的pid,注释2处调用attachApplicationLocked的方法传入pid连接application。需要注意的这边加了synchronized关键字,表示我们需要等待这里执行完毕才能下一步,也就是说我们一个应用需要当我们application被连接后才能走下面的流程。
##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
ProcessRecord app; //1、进程记录类,保存相关的信息
long startTime = SystemClock.uptimeMillis();
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid); //2、根据id获取相关信息赋值给记录对象
}
}
...
if (app.instr != null) { //3、判断进程是否正在活跃
//Application 4、绑定到当前线程
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);
} else {
//Application 4、绑定到当前线程
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, 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 {
//TODO 5、Activity创建的分析
//检测top的Activity是否在运行中等待
if (mStackSupervisor.attachApattachApplicationplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
//查看在此进程中进行的服务
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
// Check if a next-broadcast receiver is in this process...
//查看在此进程中进行的广播接收者
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
// Check whether the next backup agent is in this process...
//检测下一个备份代理是否在此进程中
if (!badApp && mBackupTarget != null && mBackupTarget.app == app) {
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
"New app is backup target, launching agent for " + app);
notifyPackageUse(mBackupTarget.appInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
try {
thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
mBackupTarget.backupMode);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
badApp = true;
}
}
...
}
看具体的attachApplicationLocked方法里面,注释1处创建了一个进程记录对象用来保存进程的相关信息,注释2根据id获取到相关信息赋值给记录对象,注释3先判断进行是否活跃,然后调用bindApplication的方法进行application的绑定,这边的thread是IApplicationThread对象,IApplicationThread它是一个AIDL的接口,是系统进程调用应用进程的接口,它的实现类是ApplicationThread,是一个在ActivityThread的内部类,注释5的地方是关于Activity的创建,我们这边先跳过,等我们将Application进行绑定完成后在来分析。
##ActivityThread.ApplicationThread
public final void bindApplication(String processName, ApplicationInfo appInfo...,String buildSerial) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);//1、添加核心设置
//2、将bindApplication带进来的信息封装到AppBindData类中,通过handler发送出去
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
...
sendMessage(H.BIND_APPLICATION, data);//3、将data通过handler发送出去,具体的WHAT 是 H.BIND_APPLICATION
}
在注释1会去添加一些核心的设置,我们这边就不去关注,我们看注释2的地方,去将带进来的信息封装到data中然后在注释3通过handler发送出去,具体的WHAT 是 H.BIND_APPLICATION。H是一个继承Handler的子类,这边我们去看下消息是如何被分发处理的。
##ActivityThread.H
public void handleMessage(Message msg) {
...
switch (msg.what) {
...
case BIND_APPLICATION:
//1、这边进行handler消息的处理 处理创建Application的消息
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData) msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
...
}
这边注释1处理创建Application的消息,调用handleBindApplication的方法去绑定application
##ActivityThread
private void handleBindApplication(AppBindData data) {
final InstrumentationInfo ii;//1、创建InstrumentationInfo对象
...
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); 2、 //获取application的context上下文
// 3、加载instrumentation
if (ii != null) {
...
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection); //4、instrumentation初始化
...
} else {
mInstrumentation = new Instrumentation();
}
try {
Application app = data.info.makeApplication(data.restrictedBackupMode, null);//5、通过makeApplication方法创建application
...
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
} catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);//6、回调application的onCreate方法
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
这个方法里面处理了许多事情,注释1创建了一个InstrumentationInfo对象,在注释2获取了application的上下文,注释3和4去加载并初始化了InstrumentationInfo,注释5是我们的关键地方,通过调用makeApplication的方法创建了我们的application,我们看下makeApplication的方法都做了什么操作。然后在注释6调用InstrumentationInfo去回调application的onCreate方法,到这里我们的application就创建并且回到了我们熟悉onCreate方法。
##LoadedApk
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {//1、如果mApplication不为null,直接返回mApplication对象
return mApplication;
}
Application app = null;
//如果是有自定义的application,就用这个,如果没有,就用系统的application
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
//2、获得类加载器然后通过反射去new一个Appliction
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;//3、赋值给mApplication
if (instrumentation != null) {//4、这边会为instrumentation是为null的
try {
instrumentation.callApplicationOnCreate(app);//5、这边如果instrumentation不为null,才能执行到这里
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
...
}
}
}
...
return app;
}
这边我们首先判断mApplication如果不为null,直接返回这个对象,如果为null的话,我们通过类加载然后反射去new出一个application对象并且赋值给mApplication,还有这边因为我们在调用makeApplication方法时传入的Instrumentation是个null对象,所以我们这边不会去执行
callApplicationOnCreate回调onCreate方法的。具体的回调onCreate会在上面的源码注释6的地方去执行回调。
二、Activity的创建
这边我们首先需要知道Activity的状态和生命周期
状态:运行、暂停、停止、销毁(运行和暂停是不可见的,停止和销毁是不可见的)
生命周期:包括了常见的onCreate、onResume、onStart、onPause、onStop、onDestory等
上面的分析过程中我们在ActivityManagerService类中留了一个
##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
//5、检测最可见的Activity是否在运行进程中等待,如果再则创建Activity
//TODO 待分析Activity的创建
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
}
...
这边我们对它进行深入下看看是如何创建的
##ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
...
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
//ActivityRecord来维护Activity运行时的状态信息,需要将Activity绑定到AMS,ActivityRecord才能开始Activity的生命周期
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (realStartActivityLocked(hr, app, true, true)) {//1、真正的创建Activity
didSomething = true;
}
} catch (RemoteException e) {
throw e;
}
}
}
}
}
...
return didSomething;
}
在realStartActivityLocked我们会创建Activity
##ActivityStackSupervisor
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
r.startFreezingScreenLocked(app, 0);//1、开始屏幕相关的启动
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();//2、启动定时锁定
r.app = app;
app.waitingToKill = null;
r.launchCount++;//3、每启动一次launchCount的数量自增
r.lastLaunchTime = SystemClock.uptimeMillis();//4、修改最后一次的启动时间
final ActivityStack stack = task.getStack();
try {
...
//5、根据具体的包名,通知应用
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
...
//6、调用ApplicationThread的scheduleLaunchActivity 方法去启动LaunchActivity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
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, !andResume,
mService.isNextTransitionForward(), profilerInfo);
...
} catch (RemoteException e) {
...
}
...
if (isFocusedStack(stack)) {
mService.startSetupActivityLocked();7、开始设置活动锁
}
if (r.app != null) {
mService.mServices.updateServiceConnectionActivitiesLocked(r.app);//8、更新服务连接活动锁
}
return true;
}
这边的注释很多,但是我们主要关心的是注释6,这边调用ApplicationThread的scheduleLaunchActivity 方法去启动LaunchActivity,我们回到ApplicationThread
##ActivityThread.ApplicationThread
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
..., ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
...
sendMessage(H.LAUNCH_ACTIVITY, r);//通过handler发送启动Activity的消息
}
这边是不是很眼熟,我们刚刚的application的绑定也是通过handler去发送消息去处理(这边我们能发现handler是有多么重要了吧,哈哈),我们去ActivityThread的子类H去看下具体的activity创建的消息处理
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {//1、接收到关于创建Activity的消息,进行处理
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//2、去创建LaunchActivity
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
根据message的what值我们找到了具体的消息处理,这边会通过handleLaunchActivity去处理我们Activity创建
##ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);//1、去执行LaunchActivity
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//2、处理可见Activity
...
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
//3、这边如何activity是个null的对象,直接通过ActivityManagerService调用finishActivity去关闭掉
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
这边我们先看注释1的performLaunchActivity方法
##ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
ActivityInfo aInfo = r.activityInfo;//1、获取Activity的信息
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
...
ContextImpl appContext = createBaseContextForActivity(r);//2、获取Acitivty的上下文
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();//3、获取类加载器,使用cl(类加载器)加载出Activity,再使用反射new出Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
//4、这边又去调用一次makeApplication方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
...
appContext.setOuterContext(activity);
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);
...
if (r.isPersistable()) {//5、这边去调用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
在注释3我们会发现这边是获取类加载去然后通过反射去new出一个Activity,然后在注释5去回调Activity的onCreate方法,到这边我们就能去调用我们的setContentView去加载布局了。注释4的地方又调用了一次makeApplication方法,如果Application不为null,直接返回application对象。
现在我们回到上一个源码的注释2那里,看看handleResumeActivity都做了什么?
##ActivityThread
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
...
r = performResumeActivity(token, clearHide, reason);
...
}
这个方法里面有很多代码,我们只需要去看performResumeActivity方法
##ActivityThread
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
...
r.activity.performResume();//主要是这个方法
...
return r;
}
这边是调用Activity的performResume方法
##Activity
final void performResume() {
performRestart();
mFragments.execPendingActions();
mLastNonConfigurationInstances = null;
mCalled = false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);//回调Activity的onResume方法
}
到这边我们就能发现它跟Activity的onCreate的回调是类似的,都是通过mInstrumentation.callActivityxxx去回调执行。
沿着别人走过的路,跟上去发现不一样的风景
参考链接:https://www.jianshu.com/p/f55467033146