宁波IT培训
美国上市IT培训机构
0574-87236644
一、前言
一个App是怎么启动起来的?
App的程序入口到底是哪里?
Activity生命周期到底是什么时候调用的?被谁调用的?
听说还有个AMS的东西,它是做什么的?它是怎样管理和启动Activity的?
ActivityThread、ApplicationThread、ActivityRecord、ActivityStack、TaskRecord都是些什么鬼?它们之间又有什么样的联系?
我们项目中遇到的关于Activity启动流程的例子?
等等...
Android应用程序的载体是APK文件,它是一个组件和资源的容器。APK文件和我们常见可执行文件的区别是:每个可执行文件在一个单独的进程中,但是APK文件可能运行在一个单独的进程也可能和其他APK文件运行在同一个进程中。Android的设计理念是弱化进程的存在,取而代之以组件的概念。
本篇知识框架:
Activity是最复杂的一种组件,它负责UI的显示以及处理各种输入事件。Activity通常表现为一个可视化的用户界面,包含了各种各样的控件,让用户来完成某项工作,例如打电话、发短信、拍照等。
我们来看一下这一张经典的生命周期流程图:
Android SDK中提供的Activity生命周期图,隐含了Activity运行时的3种状态:
激活态 :新启动的Activity位于屏幕的最前端,接收用户的输入。>>onResume()
暂停态 :当Activity被另一个透明或半透明的Activity覆盖时所处的状态,例如:Dialog。此时的Activity虽然已经不能接收用户的输入,但还是可见的。>>onPause()
停止态 :当一个Activity完全被另外一个Activity覆盖,不能接收用户输入也不可见。>>onStop()
二、Activity的生命周期
Android建立在Linux系统之上,基础的运行环境还是由进程组成。所有Android的应用进程都是由Zygote进程fork出来,因此,构成进程的底层基础,包括虚拟机、动态库等都是相同的。除了从Zygote中继承而来的基础设施外,Android需要在应用的Java层建立一套框架来管理运行的组件。由于应用的配置各不相同,因此,不能在Zygote中完全建好后再继承,只能在应用启动时创建。而这套框架就构成了Android应用的基础。
Android应用进程的核心是ActivityThread 类,App的真正入口。每启动一个App进程,都会创建ActivityThread与之对应的实例,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。这个类包含了应用框架中其他重要的类。
我们梳理一下这个ActivityThread类:
三、应用进程的组成
1、ActivityThread
public final class ActivityThread {
...
final ApplicationThread mAppThread = new ApplicationThread();
final Looper mLooper = Looper.myLooper();
final H mH = new H();
Application mInitialApplication;
Instrumentation mInstrumentation;
private final ResourcesManager mResourcesManager;
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
final ArrayMap<String, WeakReference<LoadedApk>> mPackages
= new ArrayMap<String, WeakReference<LoadedApk>>();
final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages
= new ArrayMap<String, WeakReference<LoadedApk>>();
final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
= new ArrayMap<ProviderKey, ProviderClientRecord>();
...
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser(); // 初始化应用中需要使用的系统路径
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Process.setArgV0("<pre-initialized>"); // 设置进程名称
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread(); // 创建ActivityThread实例
thread.attach(false); // 调用attach
if (sMainThreadHandler == null) { // 保存主线程的handler
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init(); // 初始化AsynTask类
Looper.loop(); // 进入消息循环
throw new RuntimeException("Main thread loop unexpectedly exited");
}
...
/**
* 调用mH发送消息排队处理事件
*/
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
...
}
mActivities、mServices和mProviderMap分别保存了应用中所有的Activity对象、Service对象和ContentProvider对象。BroadcastReceiver对象的生命周期很短暂,属于调用一次运行一次的类型,因此不需要保存其对象。
mInitialApplication变量是一个唯一的Application对象,允许自定义。
mResourceManager管理应用的资源。
mPackages和mResourcesPackages保存的是应用apk包的信息。(比如,通过属性process设置相同的应用名称后,两个有着相同ShareUserId和签名的应用可以合并在同一个进程运行)
ActivityThread 管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client、ActivityThread.ApplicationThread为Server)负责调度和执行四大组件activities、services、broadcasts、providers,以及其它操作。
main()法的逻辑比较简单,主要是初始化环境,然后让线程进入消息循环。在进行消息循环前,main方法创建了ActivityThread对象,并使用参数false调用了他的attach()方法。
我们看看attach()方法中参数为false时的分支代码:
attach()方法中主要做了两件事情,一是调用setApplicationObject()方法把对象mAppThread放到了RuntimeInit类中的静态变量mApplicationObject中。private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ...... android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); // 客户端调用ActivityManagerNative.getDefault()返回的是ActivityManagerProxy // 也就是从ServiceManger获取AMS的IBinder对象 final IActivityManager mgr = ActivityManagerNative.getDefault(); try {
logAppLaunchTime(TAG, "attachApplication -> AMS"); /// M: It's for
debugging App Launch time
mgr.attachApplication(mAppThread); // 调用AMS的attachApplication方法 } catch (RemoteException ex) { // Ignore } ...... } else { ...... } } }
public class RuntimeInit {
......
public static final void setApplicationObject(Ibinder app) {
mApplicationObject = app;
}
......
}
第二件事情是调用ActivityManagerService的attachApplication方法,同时将mAppThread作为参数传递给了AMS中,这样AMS就能通过它来调用应用的接口了(Binder通信)。attachApplication方法最终实现是attachApplicationLocked。
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
......
try {
......
// 调用应用的bindApplication接口
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
......
} catch (Exception e) {
......
return false;
}
......
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
// 调用mStackSupervisor.attachApplicationLocked接口
// 如果进程没有启动,最后就是调用realStartActivityLocked()启动进程
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
badApp = true;
}
}
// Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
Slog.e(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);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
......
}
......
}
attachApplicationLocked()方法首先检查调用的参数,然后又回调ApplicationThread的接口bindApplication(),bindApplication()发送完消息BIND_APPLICATION然后就返回了,这样执行过程就转到应用的消息处理代码中。除了开启Activity能启动进程外,启动Service、发送广播也可能需要启动进程,因此,这里也调用了mServices.attachApplication()方法,以及sendPendingBroadcastsLocked来启动进程。
下面再回头看看ActivityThread是如何处理BIND_APPLICATION消息的。
private void handleBindApplication(AppBindData data) { mBoundApplication = data; // 创建系统配置对象 mConfiguration = new Configuration(data.config); mCompatConfiguration = new Configuration(data.config); ...... // 设置进程的名称和DDMS中的进程名 Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId()); if (data.persistent) { // 带有Persistent标记的进程在低内存的设备上不能使用硬件加速 if (!ActivityManager.isHighEndGfx()) { /// M: ALPS01978329 for 512m project final long LOW_MEMORY_SIZE = 256 * 1024 * 1024; MemInfoReader minfo = new MemInfoReader(); minfo.readMemInfo();
if ((minfo.getTotalSize() <= LOW_MEMORY_SIZE) || (!".systemui".
equals
(data.processName))) {HardwareRenderer.disable(false);
Slog.w(TAG, "Disable HWUI for Process(" + data.processName + ");
Total Memory = " + minfo.getTotalSize());
} } } ...... // 用系统的配置设置应用的时区 TimeZone.setDefault(null); // 用系统的配置设置应用的地区 Locale.setDefault(data.config.locale); // 生成资源管理对象mResourcesManager,并用系统配置初始化 mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi; applyCompatConfiguration(mCurDefaultDisplayDpi); ...... // 生成ContentImpl对象 final ContextImpl appContext = ContextImpl.createAppContext(this, ); if (!Process.isIsolated()) { // 设置cache目录 final File cacheDir = appContext.getCacheDir(); if (cacheDir != null) { // Provide a usable directory for temporary files System.setProperty(".tmpdir", cacheDir.getAbsolutePath()); } else {
Log.v(TAG, "Unable to initialize \".tmpdir\" property
due to missing cache directory");
} // Use codeCacheDir to store generated/compiled graphics code final File codeCacheDir = appContext.getCodeCacheDir(); if (codeCacheDir != null) { setupGraphicsSupport(, codeCacheDir); } else { Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory"); } } ...... IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { // 设置网络代理 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { final ProxyInfo proxyInfo = service.getProxyForNetwork(null); Proxy.setHttpProxySystemProperty(proxyInfo); } catch (RemoteException e) {} } if (data.instrumentationName != null) { ...... } else { // 创建Instrumentation对象 mInstrumentation = new Instrumentation(); } if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { // 如果应用指定使用big heap,则清除dalvik中的限制 dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { // Small heap, clamp to the current growth limit and let the heap release // pages after the growth limit to the non growth limit capacity. b/18387825 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); } final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); try { // 最终,生成Application对象 Application app = .makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; if (!data.restrictedBackupMode) { List<ProviderInfo> providers = data.providers; if (providers != null) { // 初始化应用的ContentProvider installContentProviders(app, providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } try { // 调用mInstrumentation对象的onCreate()方法 mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { // 调用Application对象的onCreate()方法 mInstrumentation.callApplicationOnCreate(app); } 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); } }
handleBindApplication()方法的主要功能就是创建应用框架中的各种对象,这些对象大都已经介绍过了。最终调用到应用的Application.onCreate(),整个应用进程也就创建完毕。
ApplicationThread是ActivityThead的一个内部类,是一个Binder服务类,ActivityManagerService操作应用就是通过ApplicationThread提供的接口完成的。
final ApplicationThread mAppThread = new ApplicationThread();
private class ApplicationThread extends ApplicationThreadNative {
...
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
configChanges);
}
public final void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) {
sendMessage(
showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
token, 0, configChanges);
}
public final void scheduleSleeping(IBinder token, boolean sleeping) {
sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
}
public final void scheduleResumeActivity(IBinder token, int processState,
boolean isForward, Bundle resumeArgs) {
updateProcessState(processState, false);
sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
}
public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
ResultData res = new ResultData();
res.token = token;
res.results = results;
sendMessage(H.SEND_RESULT, res);
}
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
...
}
ApplicationThread类从ApplicationThreadNative类派生,ApplicationThreadNative类中封装了Binder的实现。ApplicationThread虽然定义了大量的接口,但是接口的实现模式都是把Binder调用转换成**mH 的消息来排队处理 **。
消息的处理最终会调用ActivityThread类的某个方法完成。 通过这种模式,从Binder来的调用就转换成异步的方式来执行了。理解了这个过程之后,再分析ApplicationThread类的接口是时,我们可以忽略中间的消息传递过程,直接查看ActivityThread中对应的方法。
5、H(Handler)消息处理
final H mH = new H();
private class H extends Handler {
...
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
...
}
未完待续 >>>
文章转载于