四大組件概述
- Activity绎狭,是一種展示型組件细溅,用于向用戶展示UI。它只有一種運(yùn)行模式:處于啟動(dòng)狀態(tài)儡嘶。
- Service喇聊,是一種計(jì)算型組件,用于在后臺(tái)執(zhí)行一系列計(jì)算任務(wù)蹦狂。它有兩種狀態(tài):?jiǎn)?dòng)狀態(tài)和綁定狀態(tài)誓篱。Service是運(yùn)行在主線程的,因此耗時(shí)的任務(wù)需要在工作線程去完成凯楔。Service處于綁定狀態(tài)時(shí)窜骄,它內(nèi)部同樣可以進(jìn)行后臺(tái)計(jì)算。
- BroadCastReceiver摆屯,是一種消息行組件邻遏,用于在不同的組件甚至不同應(yīng)用間傳遞消息。靜態(tài)注冊(cè)在應(yīng)用安裝時(shí)會(huì)被系統(tǒng)解析虐骑,不需要應(yīng)用啟動(dòng)就能收到相應(yīng)的廣播准验;動(dòng)態(tài)注冊(cè)必須要應(yīng)用啟動(dòng)后才能收到廣播。
- ContentProvider廷没,是一種數(shù)據(jù)共享型組件糊饱,用于向其他組件甚至其他應(yīng)用共享數(shù)據(jù)。它對(duì)數(shù)據(jù)集合的具體實(shí)現(xiàn)沒(méi)有要求颠黎,可以是數(shù)據(jù)庫(kù)另锋,List滞项、Map甚至文件等。它內(nèi)部的insert砰蠢、delete蓖扑、update和query方法需要處理好線程同步唉铜,因?yàn)檫@幾個(gè)方法是運(yùn)行在Binder線程池中的台舱。ContentProvider不需要手動(dòng)停止。
Activity的工作過(guò)程
一張圖說(shuō)明Activity的啟動(dòng)流程:
performLaunchActivity這個(gè)方法主要完成如下幾件事:
1潭流、從ActivityClientRecord中獲取待啟動(dòng)的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竞惋、通過(guò)Instrumention的newActivity方法使用類加載器創(chuàng)建Activity對(duì)象
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、通過(guò)LoadedApk的makeApplication方法來(lái)嘗試創(chuàng)建Application對(duì)象
LoadedApk.calss
被標(biāo)記為@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創(chuàng)建完畢后拆宛,系統(tǒng)會(huì)通過(guò)Instrumention的callApplicationOncreate來(lái)調(diào)用Application的onCreate方法
4、創(chuàng)建ContextImpl對(duì)象并通過(guò)Activity發(fā)attach方法來(lái)完成一些重要數(shù)據(jù)的初始化
5讼撒、調(diào)用Activity的onCreate方法
Service的工作過(guò)程
Service的啟動(dòng)過(guò)程
一張圖說(shuō)明Service的啟動(dòng)流程:
handleCreateService方法主要完成如下幾件事:
1浑厚、通過(guò)類加載器創(chuàng)建Service的實(shí)例
2、創(chuàng)建Application對(duì)象并調(diào)用其onCreate方法
3根盒、創(chuàng)建ContextImpl對(duì)象并通過(guò)Service發(fā)attach方法建立二者之間的關(guān)系
4钳幅、調(diào)用Service的onCreate方法并將Service對(duì)象存儲(chǔ)到ActivityThread中的一個(gè)列表中。ActivityThread通過(guò)handleServiceArgs方法調(diào)用Service的onStarCommand方法
Service的綁定過(guò)程
一張圖說(shuō)明Service的綁定過(guò)程:
handleBindService方法主要完成如下幾件事:
1炎滞、根據(jù)Service的token取出Service對(duì)象敢艰,調(diào)用Service的onBind方法
2、通過(guò)ActivityManagerService調(diào)用publishService方法通知客戶端已經(jīng)成功連接Service
BroadcastReceiver的工作過(guò)程
Activity册赛、Service钠导、ContentProvider和BroadcastReceiver的靜態(tài)注冊(cè)都是在應(yīng)用安裝時(shí)由PackageManagerService解析注冊(cè)的。
BroadcastReceiver的注冊(cè)過(guò)程
BroadcastReceiver的發(fā)送和接收過(guò)程
自Android3.1開(kāi)始森瘪,系統(tǒng)為Intent新增了兩個(gè)標(biāo)志牡属,并為所有廣播默認(rèn)添加 FLAG_EXCLUDE_STOPPED_PACKAGES
標(biāo)志,防止無(wú)意間或者在不必要的時(shí)候喚醒已經(jīng)停止的APP扼睬,這個(gè)特性同樣會(huì)影響開(kāi)機(jī)廣播
- FLAG_INCLUDE_STOPPED_PACKAGES
表示包含已經(jīng)停止的APP逮栅,這個(gè)時(shí)候廣播會(huì)發(fā)送到已經(jīng)停止的APP - FLAG_EXCLUDE_STOPPED_PACKAGES
表示不包含已經(jīng)停止的APP,這個(gè)時(shí)候廣播不會(huì)發(fā)送給已經(jīng)停止的APP
當(dāng)兩個(gè)標(biāo)志共存時(shí)痰驱,以 FLAG_INCLUDE_STOPPED_PACKAGES
為準(zhǔn)
ContentProvider的工作過(guò)程
當(dāng)ContentProvider所在的進(jìn)程啟動(dòng)時(shí)证芭,ContentProvider會(huì)同時(shí)啟動(dòng)并被發(fā)布到ActivityManagerService中,這個(gè)時(shí)候ContentProvider的onCreate要先于Application的onCreate執(zhí)行担映。
ActivityThread的handleBindApplication方法最終完成Application和ContentProvider的創(chuàng)建废士,步驟如下:
- 創(chuàng)建ContextImpl和Instrumention
- 創(chuàng)建Application對(duì)象
- 啟動(dòng)當(dāng)前進(jìn)程的ContentProvider并調(diào)用其onCreate方法
- 調(diào)用Application的onCreate方法