@[TOC]
1. Activity启动模式以及使用场景?
- standard 标准模式 使用场景: 邮件,默认使用标准模式
- singleTop 栈顶复用 :登录页面 ,微信支付 微信回调,推送通知栏等
- singleTask 栈内单例模式: 主页面等重复调用的页面
- singleInstance 栈内单例模式 系统Launcher, 锁屏页面等,此种模式下系统会为这个模式下的Activity单独开辟一个栈
- 总结 singleTop ,singleTask ,singleInstance 三种模式如果应用内存在Activity的实例,就不会重新去创建Activity的实例,而是调用Activity的onNewIntent函数 从而Activity的oncreate和onstart没有被调用
- 关于singleInstance 必须知道的故事一: 此时有三个activity,ActivityA,ActivityB,ActivityC,除了ActivityB的启动模式为singleInstance,其他的启动模式都为默认的。在ActivityA里startActivity了一个ActivityB,在ActivityB里startActivity了一个ActivityC。照理来说在当前ActivityC页面按返回键,finish当前界面后应当回到ActivityB界面,但是页面直接回到了ActivityA。
- 分析 singleInstance模式是存在于另一个任务栈中的。也就是说ActivityA和ActivityC是处于同一个任务栈中的,ActivityB则是存在另个栈中。所以当关闭了ActivityC的时候,它自然就会去找当前任务栈存在的activity。当前的activity都关闭了之后,才会去找另一个任务栈中的activity。也就是说当在ActivityC中finish之后,会回到ActivityA的界面,在ActivityA里finish之后会回到ActivityB界面。
- 故事二:有两个ActivityA,ActivityB,ActivityA的启动模式为默认的,ActivityB的启动模式为singleInstance。当在ActivityA里startActivity了ActivityB,当前页面为ActivityB。按下home键。应用退到后台。此时再点击图标进入APP,按照天理来说,此时的界面应该是ActivityB,可是奇迹又出现了,当前显示的界面是ActivityA。
- 分析 这是因为当重新启动的时候,系统会先去找主栈(我是这么叫的)里的activity,也就是APP中LAUNCHER的activity所处在的栈。查看是否有存在的activity。没有的话则会重新启动LAUNCHER。
- 说了这么多 如果想让Activity回到我们想让它返回的地方如何做呢?
- 解答在ActivityB定义一个全局变量,public static boolean returnActivityB;界面需要跳转的时候将returnActivityB=true;然后在ActivityA界面onstart方法里判断returnActivityB是否为true,是的话就跳转到ActivityB,同时将returnActivityB=false;这样就能解决跳转的问题了
2. taskAffinity属性
taskAffinity属性和Activity的启动模式息息相关, 这个属性在mainfest中设置,可以理解为taskAffinity为宿主Activity指定了存放的任务栈, taskAffinity只有和singleTask启动模式匹配使用,启动的Activity才会运行在名字和taskAffinity相同的任务栈中
3. onSaveInstanceState()和onRestoreInstanceState()
Activity中出现异常关闭时候,尽管实际的Activity已经销毁,但是Android系统会记住它已经存在,系统会创建一个新的实例的Activity使用一组保存的数据来描述Activity在被销毁的状态,这组数据存储在Binder对象的键值对的集合中.
-
onSaveInstanceState 保存你的Activity状态.
@Override protected void onSaveInstanceState(Bundle outState) { outState.putString("Activity_State","需要保存的数据"); // 调用父类交给系统处理,这样系统能保存视图层次结构状态 super.onSaveInstanceState(outState); }
-
onRestoreInstanceState()
@Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); //得到异常状态下的实例保存的数据 String state = savedInstanceState.getString("Activity_State"); }
以上二种onSaveInstanceState()和onRestoreInstanceState()触发条件只在Activity异常情况下触发,正常情况下的Activity不会执行以上二个方法,可以自行验证. 具体使用的话如当前页面接受到另外页面传递过来的数据,而且当前页面可能存在奔溃情况, 可以用到这二个方法.
4. onConfigurationChanged()属性屏幕旋转
-
当系统的配置信息发生改变时,系统才会调用此方法,只有在配置文件AndroidMainfest中处理了configChanges属性,对应的设备配置,该方法才会被调用,
<activity android:configChanges="screenSize|orientation" android:name=".MainActivity" android:label="@string/app_name">
当屏幕方向发生改变时,Activity会被销毁重建,如果在AndroidMainfest中添加处理屏幕方向配置信息,则Activity不会被销毁,而是调用onConfigurationChanged 方法
-
configChanges设置取值
-
当用户接入一个外接键盘时,默认软键盘会隐藏,系统会自动使用外设键盘,这个过程中Activity的销毁和隐藏执行了二次,并且onConfigurationChanged()方法不会调用,但是在配置文件中设置
android:configChanges="keyboardHidden|keyboard"
。当接入外设键盘或者拔出外设键盘时,调用的周期是先调用onConfigurationChanged()周期后销毁重建分析,为何会二次销毁重建. 一次是键盘的插入当设置
android:configChanges="keyboardHidden|keyboard"
之后,就不会销毁重建,而是调用onConfigurationChanged()方法。但是还有一次销毁重建一直存在. 经过测试发现,接入了外设,除了改变键盘类型的改变,触摸屏也发生改变,
-
总结 如果键盘类型发生改变,
configChanges
属性配置如下的Activity才不会销毁重建,且回调onConfigurationChanged
方法:<activity android:configChanges="keyboard|keyboardHidden|touchscreen" android:name=".MainActivity" android:label="@string/app_name">
5. (主要)Activity 到底是如何启动的
- 主要分为4个部分来叙述整个Activity是如何启动的
- 涉及的名词简介,
- Launcher请求AMS过程
3.AMS到ActivityThread的调用过程,
4.ActivityThread启动Activity的过程
1. 涉及的类名介绍:
-
ActivityManagerServices
简称AMS 服务端对象,负责整个系统中Activity的生命周期 -
ActivityThread
App的入口, 当App开启后,会调用它的main()
方法开始运行,main()
主要就是开启一个消息循环队列,与AMS配合完成Activity的管理工作, (ActivityThread就是UI线程或者主线程). -
ApplicationThreadProxy
是ApplicationThread在服务器端的代理对象,负责和客户端的ApplicationThread通讯,但是在android8以后,ApplicationThreadProxy
被IApplicationThread
取代了,IApplicationThread
实际上实现的ApplicationThread -
instrumentation
每个应用程序只有一个instrumentation
对象每个Activity内部都有一个对改对象的引用,很多时候理解为应用程序进程管家,ActivityThread
要创建或者暂停某个Activity时候,都需要instrumentation
对象来进行具体操作 -
ActivityStack
Activity在AMS的栈管理,用来记录已经启动的Activty的先后关系,状态信息等,通过ActivityStack
决定是否需要启动新的进程. -
ActivityRecord
ActivityStack的管理对象,每个Activity在AMS对应的ActivityRecord,来记录Activity的状态以及其他管理信息,其时就是服务端的Activity对象的映像, -
TaskRecord
AMS抽象出来的一个任务概念,记录ActivityRecord的栈,一个Task包含若干个ActivityRecord,AMS用TaskRecord确保Activity启动和退出的顺序,
2. Launcher请求AMS的过程
此处省略init进程的创建,Zygote进程, SystemService,Launcher进程的创建.如果想了解的请自行查看资料和源码
-
Launcher是一个Activity, 它的作用就是创建一个桌面程序,存放日常App的入口,
public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, View.OnTouchListener { ... Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { onClickAppShortcut(v); //点击应用图标 } else if (tag instanceof com.android.launcher3.FolderInfo) { if (v instanceof FolderIcon) { onClickFolderIcon(v); //点击文件夹 } } else if ((FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && v instanceof PageIndicator)||(v == mAllAppsButton && mAllAppsButton != null)) { onClickAllAppsButton(v); } else if (tag instanceof AppInfo) { startAppShortcutOrInfoActivity(v); //启动应用程序的入口 } else if (tag instanceof com.android.launcher3.LauncherAppWidgetInfo) { if (v instanceof com.android.launcher3.PendingAppWidgetHostView) { //小部件 onClickPendingWidget((com.android.launcher3.PendingAppWidgetHostView) v); } } ... private void startAppShortcutOrInfoActivity(View v) { com.android.launcher3.ItemInfo item = (com.android.launcher3.ItemInfo) v.getTag(); Intent intent = item.getIntent(); if (intent == null) { throw new IllegalArgumentException("Input must have a valid intent"); } //开始启动Activity了. 发现startActivitySafely()其实当我们点击桌面任意图标的时候都会触发这个方法 boolean success = startActivitySafely(v, intent, item); //判断启动Activity是否成功 getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115 if (success && v instanceof BubbleTextView) { mWaitingForResume = (BubbleTextView) v; mWaitingForResume.setStayPressed(true); } } ... }
我们继续跟踪startActivitySafely()方法,
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { ... //根Activity会在新的任务栈中启动,标志启动一个新的activity intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { if (Utilities.ATLEAST_MARSHMALLOW && (item instanceof ShortcutInfo) && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) && !((ShortcutInfo) item).isPromise()) { //检查快捷方式 里面也会调用startActivity()方法 startShortcutIntentSafely(intent, optsBundle, item); } else if (user == null || user.equals(Process.myUserHandle())) { //启动Activity.startActivity()方法 startActivity(intent, optsBundle); } .... }
回到Activity中查看startActivity方法
@Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } }
在
startActivityForResult
中可以看到调用了Instrumentation.execStartActivity()
方法 并且得到一个Instrumentation的对象public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) {//mParent表示根Activity 即Launcher options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(//监控应用程序和系统交互 this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, opions);
Instrumentation.execStartActivity
方法的具体实现public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { ... IApplicationThread whoThread = (IApplicationThread) contextThread; try { String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { intents[i].migrateExtraStreamToClipData(); intents[i].prepareToLeaveProcess(who); resolvedTypes[i] =intents[i].resolveTypeIfNeeded (who.getContentResolver()); } // 通过Aidl的方式得到AMS在本地的代理类IActivityManager,通知AMS执行startActivities方法; int result = ActivityManager.getService() .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,token, options, userId); checkStartActivityResult(result, intents[0]); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } }
ActivityManager.getService()
public static IActivityManager getService() { return IActivityManagerSingleton.get(); } //单例模式 private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);//IBnder的类型的AMS //将IBinder对象转换成IActivityManager //此处用的是binder的AIDL方式得到一个转化后的IActivityManager对象,IActivityManager对象是AMS在本地的代理 final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
简单总结一下: 以下的流程完成了Launcher请求AMS的过程
3. AMS到ActivityThread的调用过程
AMS收到startActivity的请求之后,会按照如下的方法链进行调用
//AMS中Activity的启动入口
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
在这里又出现了一个新对象ActivityStackSupervisor,通过这个类可以实现对ActivityStack的部分操作
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
//判断调进程用者是否被隔离 如果隔离会有SecurityException异常
enforceNotIsolatedCaller("startActivity");
//检查调用者权限 没有权限也会有SecurityException异常
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
ActivityStarter类中的操作
final int startActivityMayWait(IApplicationThread caller, int callingUid,...){
...
//这个ActivityStarter主要作用,加载Activity控制类,收集所有的逻辑来决定intent和flags转为 //Activity并且将Activity和Task以及Stack相关联
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask, reason);
...
}
int startActivityLocked(...) {
if (TextUtils.isEmpty(reason)) { //启动理由reason
throw new IllegalArgumentException("Need to specify a reason.");
}
...
//startActivity()
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,container, inTask);
...
return mLastStartActivityResult;
}
private int startActivity(...){
...
// 即将要启动的Activity的描述类ActivityRecord (用来记录Activty的所有信息)
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
...
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
private int startActivity(...) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
}
...
return result;
}
private int startActivityUnchecked(...) {
...
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
...
}
ActivityStackSupervisor # resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
//获取要启动的Activity 并且所在栈的栈顶的不是处于停止状态的ActivityRecord
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
//继续执行ActivityStack # resumeTopActivityUncheckedLocked
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
ActivityStack # resumeTopActivityUncheckedLocked
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
//继续执行
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
mStackSupervisor.checkReadyForSleepLocked();
return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
...
mStackSupervisor.startSpecificActivityLocked(next, true, true);
...
}
ActivityStackSupervisor # startSpecificActivityLocked
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
//获取即将要启动的Activity的所在的应用程序进程
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
//判断要启动的 Activity 所在的应用程序进程如果已经运行
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//继续执行
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
final boolean realStartActivityLocked(...){
...
//app.thread 指的IApplicationThread它的实现是 ActivityThread 的内部类 ApplicationThread
// 段代码指的就是要在目标应用程序进程启动 Activity
//app指的是传入的要启动的Activity所在的应用程序进程 代码只要目的就是要在目标引用程序启动Activity
//当前代码运行在AMS所在的基础进程(SystemServer进程)中,通过ApplicationThread来与应用程序进行BInder 通信,所以ApplicationThread就是AMS和应用程序通信的桥梁
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
...
}
看一下时序图再说 源码来回切换有点乱
4. ActivityThread启动Activity的过程
ActivityThread通过BInder接收到AMS发送过来的启动Activity的启动通知调用ApplicationThread的scheduleLaunchActivity方法 因为AMS启动Activity的时候用的 app.thread.scheduleLaunchActivity
而app.thread
是调用ProcessRecord.IApplicationThread
对象,ApplicationThread
继承于IApplicationThread.stub
所以执行ActivityThread#ApplicationThread#scheduleLaunchActivity方法
private class ApplicationThread extends IApplicationThread.Stub {
...
@Override
public final void scheduleLaunchActivity(){
...
//得到Binder传递过来的消息封装到ActivityClientRecord对象中发送给H H是一个消息进程管理类
sendMessage(H.LAUNCH_ACTIVITY, r);
}
...
}
ActivityThread#H #handleMessage
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
//将ApplicationThread传递过来的参数转换成ActivityClientRecode对象
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
//应用程序进程需要启动Activity时需要将改Activity所属的APK加载进来
//而 r.packageInfo返回一个loadedAPk,loadedAPk就是用来描述已加载APK文件的
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//继续执行
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
}
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { ....
//初始化WindowManager
WindowManagerGlobal.initialize();
//启动Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//将Activity的状态设置为Resume
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
//去执行将Activity状态设置为Resume
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
//如果出现错误通知AMS关闭当前Activity
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
appContext.setOuterContext(activity);
//初始化Activity activity.attach方法中会创建Window对象并且与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);
...
//Instrumentation.callActivityOnCreate来启动Activity 继续执行
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
....
}
Instrumentation#callActivityOnCreate
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
Activity#performCreate
final void performCreate(Bundle icicle) {
//释放启动Activity过程中需要的权限
restoreHasCurrentPermissionRequest(icicle);
//调用Activity的onCreate方法 ,根Activity就启动完毕
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
终于一个完成的Activity到此就启动完成了...看一下时序图吧 -眼睛都疼....
上面这些调用过程非常复杂,源码中各种条件判断让人眼花缭乱,所以说如果你没记住也没关系,你只要记住这个流程,理解了Android在控制Activity生命周期时是如何操作,以及是通过哪几个关键的类进行操作的就可以了,
总结一下 Activity的启动流程:
用户在Launcher程序里点击应用图标时,会通知AMS启动应用的入口Activity,AMS发现这个应用还未启动,则会通知Zygote进程孵化出应用进程,然后在这个dalvik应用进程里执行ActivityThread的main方法。应用进程接下来通知AMS应用进程已启动,AMS保存应用进程的一个代理对象,这样AMS可以通过这个代理对象控制应用进程,然后AMS通知应用进程创建入口Activity的实例,并执行它的生命周期方法
现在也可以理解:
如果应用的组件(包括所有组件Activity,Service,ContentProvider,Receiver) 被启动,肯定会先启动以应用包名为进程名的进程,这些组件都会运行在应用包名为进程名的进程里,并且是在主线程里。应用进程启动时会先创建Application对象,并执行Application对象的生命周期方法,然后才启动应用的组件。
有一种情况比较特殊,那就是为组件设置了特殊的进程名,也就是说通过android:process设置进程名的情况,此时组件运行在单独的进程内。
- 记录集
不要使用 startActivityForResult(intent,RESULT_OK) 特此记录
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
//但是RESULT_OK = -1;
public static final int RESULT_OK = -1;
//得出结论 如果用RESULT_OK 作为请求码 你不可能从onActivityResult()里面收到任何回调.
startActivityForResult(intent,RESULT_OK) = startActivity()
本文链接地址