四大组件概述
- Activity,是一种展示型组件,用于向用户展示UI。它只有一种运行模式:处于启动状态。
- Service,是一种计算型组件,用于在后台执行一系列计算任务。它有两种状态:启动状态和绑定状态。Service是运行在主线程的,因此耗时的任务需要在工作线程去完成。Service处于绑定状态时,它内部同样可以进行后台计算。
- BroadCastReceiver,是一种消息行组件,用于在不同的组件甚至不同应用间传递消息。静态注册在应用安装时会被系统解析,不需要应用启动就能收到相应的广播;动态注册必须要应用启动后才能收到广播。
- ContentProvider,是一种数据共享型组件,用于向其他组件甚至其他应用共享数据。它对数据集合的具体实现没有要求,可以是数据库,List、Map甚至文件等。它内部的insert、delete、update和query方法需要处理好线程同步,因为这几个方法是运行在Binder线程池中的。ContentProvider不需要手动停止。
Activity的工作过程
一张图说明Activity的启动流程:
performLaunchActivity这个方法主要完成如下几件事:
1、从ActivityClientRecord中获取待启动的Activity的组件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
2、通过Instrumention的newActivity方法使用类加载器创建Activity对象
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
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) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
3、通过LoadedApk的makeApplication方法来尝试创建Application对象
LoadedApk.calss
被标记为@hide
类,源码在sdk/sources/android-22/android/app目录下
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
// Rewrite the R 'constants' for all library apks.
SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
.getAssignedPackageIdentifiers();
final int N = packageIdentifiers.size();
for (int i = 0; i < N; i++) {
final int id = packageIdentifiers.keyAt(i);
if (id == 0x01 || id == 0x7f) {
continue;
}
rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
}
return app;
}
Application创建完毕后,系统会通过Instrumention的callApplicationOncreate来调用Application的onCreate方法
4、创建ContextImpl对象并通过Activity发attach方法来完成一些重要数据的初始化
5、调用Activity的onCreate方法
Service的工作过程
Service的启动过程
一张图说明Service的启动流程:
handleCreateService方法主要完成如下几件事:
1、通过类加载器创建Service的实例
2、创建Application对象并调用其onCreate方法
3、创建ContextImpl对象并通过Service发attach方法建立二者之间的关系
4、调用Service的onCreate方法并将Service对象存储到ActivityThread中的一个列表中。ActivityThread通过handleServiceArgs方法调用Service的onStarCommand方法
Service的绑定过程
一张图说明Service的绑定过程:
handleBindService方法主要完成如下几件事:
1、根据Service的token取出Service对象,调用Service的onBind方法
2、通过ActivityManagerService调用publishService方法通知客户端已经成功连接Service
BroadcastReceiver的工作过程
Activity、Service、ContentProvider和BroadcastReceiver的静态注册都是在应用安装时由PackageManagerService解析注册的。
BroadcastReceiver的注册过程
BroadcastReceiver的发送和接收过程
自Android3.1开始,系统为Intent新增了两个标志,并为所有广播默认添加 FLAG_EXCLUDE_STOPPED_PACKAGES
标志,防止无意间或者在不必要的时候唤醒已经停止的APP,这个特性同样会影响开机广播
- FLAG_INCLUDE_STOPPED_PACKAGES
表示包含已经停止的APP,这个时候广播会发送到已经停止的APP - FLAG_EXCLUDE_STOPPED_PACKAGES
表示不包含已经停止的APP,这个时候广播不会发送给已经停止的APP
当两个标志共存时,以 FLAG_INCLUDE_STOPPED_PACKAGES
为准
ContentProvider的工作过程
当ContentProvider所在的进程启动时,ContentProvider会同时启动并被发布到ActivityManagerService中,这个时候ContentProvider的onCreate要先于Application的onCreate执行。
ActivityThread的handleBindApplication方法最终完成Application和ContentProvider的创建,步骤如下:
- 创建ContextImpl和Instrumention
- 创建Application对象
- 启动当前进程的ContentProvider并调用其onCreate方法
- 调用Application的onCreate方法