本文主要讲解activity的生命周期,启动模式和工作过程
1.生命周期,主要分为正常情况下的生命周期和异常情况下的生命周期
正常情况下的生命周期:
谈到生命周期,不得不提到下面的图片,相比很多人都已经很了解了,就不多做介绍了
但我还要提一下
1.如果activity采用了透明的主题,那么当前activity、不会调用onStop方法
2.A启动B,B是在A调用了onPause之后才会启动,onCreat-onStart-onResume,然后调用A的onStop方法。所以我们不能在onPause内做重量级的操作,这样会影响新界面的开启,如果必须要做最好在onStop中,但也尽量少做。
异常情况下的生命周期:
1.资源相关的系统配置发生改变导致Activity被杀死后重建(横竖屏切换)
2.资源内存不足导致activity被杀死
onSaveInstanceState这个方法是在onDestory之前调用的和onPause没有关系,但实际基本都是onPause之后,onStop之前调用
onRestoreInstanceState是在onStart之后,onResume之前调用
2.activity的启动模式
standard:标准模式,Activity默认会进入启动它的Activity所属的任务栈中,也就是谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。
当我们用ApplicationContext去启动standard模式的activity时会报错,因为非Activity类型的Context(如:ApplicationCotext)并没有任务栈。
解决办法:使用FLAG_ACTIVITY_NEW_TASK标记,其实也就是在代码中改变了activity的启动模式,改成了singleTask的启动模式了。
singleTop:栈顶复用模式,ABC再开启C,还是ABC而不是ABCC。
singleTask:栈内复用模式,如果A是singleTask模式,那么启动A时,先回判断是否存在A需要的栈,不存在则创建一个任务栈并创建A实例放入栈中;存在则判断栈内是否存在A的实例,不存在则创建A实例放入栈中,存在将A调到栈顶并调用它的onNewIntent方法。(将栈内A上面的Activity全部清除)
singleInstance:单实例模式,栈内只有一个此模式的activity。
最后说一下taskAffinity(任务栈)和Activity的Flags:
taskAffinity一般情况下会和singleTask或者allowTaskReparenting配合使用,用于给activity设置任务栈,默认的任务栈是包名;
allowTaskReparenting用来标记Activity能否从启动的Task移动到taskAffinity指定的Task,默认是继承至application中的allowTaskReparenting=false,如果为true,则表示可以更换;false表示不可以。
引用网上的解释例子:
一般来说,当Activity启动后,它就与启动它的Task关联,并且在那里耗尽它的整个生命周期。当当前的Task不再显示时,你可以使用这个特性来强制Activity移动到有着affinity的Task中。例如,如果e-mail中包含一个web页的链接,点击它就会启动一个Activity来显示这个页面。这个Activity是由Browser应用程序定义的,但是,现在它作为e-mail Task的一部分。如果它重新宿主到Browser Task里,当Browser下一次进入到前台时,它就能被看见,并且,当e-mail Task再次进入前台时,就看不到它了。
Activity的Flags(常用的):1.FLAG_ACTIVITY_NEW_TASK 相当于singleTask
2.FLAG_ACTIVITY_CLEAR_TOP 一般和FLAG_ACTIVITY_NEW_TASK配合使用,清除上面的activity
3.FLAG_ACTIVITY_SINGLE_TOP 相当于singleTop
4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 就是长按android的home键,然后清除刚才看的应用,这个属性的作用恰恰就是让你在长按home键的时候在弹出的应用列表中隐藏你的应用,达到隐藏应用程序进行的目的。(和android:excludeFromRecents="true"功能一样)
本人测试了一下:
android:excludeFromRecents="true" android:launchMode="singleInstance"
这样才管用,可能是excludefromrecents要配合singleInstance才可以(不知道是不是这样的,不太确认)
3.activity的启动过程
activity是一种展示型组件,用于向用户直接展示一个界面,并且可以根据用户输入的信息进行交互。
我们通常是通过startActivity或者startActivityForResult来启动一个新activity,而它们又有好几种重载方法,但最终都会调用到Activity类中startActivityForResult的方法:
(1)在Activity.java文件中:
(2)Instrumentation的execStartActivity方法:在Instrumentation.java文件中。
在上面的代码中可以看到这一句:checkStartActivityResult(result, intent);我们去看看这个方法的源码:
ActivityManagerNative.getDefault实际上就是ActivityManagerService,因此Activity的启动过程转移到了ActivityManagerService中。
可以看出,Activity的启动过程转移到了ActivityStackSupervisor的startActivityMayWait方法中了,在startActivityMayWait中有去调用startActivityLocked方法,然后startActivityLocked方法又调用startActivityUncheckedLocked方法,接着startActivityUncheckedLocked又调用了ActivitStack的resumeTopActivityLocked,这个时候启动过程已经从ActivityStackSupervisor转移到了ActivitStack。
(5)ActivitStack的resumeTopActivityLocked方法如下:
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
mService.updateSleepIfNeededLocked();
}
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
可以看出来
resumeTopActivityLocked调用了resumeTopActivityInnerLocked方法,而resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisor的startSpecificActivityLocked方法。
startSpecificActivityLocked的源码如下:
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
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);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
可以看出来startSpecificActivityLocked方法调用了realStartActivityLocked方法。
至此,我们的调用先暂停一下,我们用一张图感观的看一下刚刚的多层调用:
(6)在ActivityStackSupervisor的realStartActivityLocked方法中有如下一段代码:
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 pendingResults, List pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
(9)接下来看一下Handler H对消息的处理:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
/*
* 第一步:从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);
}
/*
* 第二步:通过Instrumentation的newActivity方法使用类加载器创建Activity对象。
* */
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
/*
* 通过类加载器创建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) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
/*
* 第三步:通过LoadedApk的makeApplication方法来尝试创建Application对象,
* 而且一个应用只能有一个Application对象。
* Application对象的创建也是通过Instrumentation来完成的,这个过程和Activity对象的创建一样,
* 都是通过类加载器来实现的。
* Application创建完毕后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate方法。
* */
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
/*
* 第四步:创建ContextImpl对象并通过Activity的attach方法来完成一些重要数据的初始化。
* 这里有一堆Activity运行过程中所依赖的上下文环境变量,
* 并通过Activity的attach方法来将这些环境变量与Activity相关联:
* (2)ContextImpl是一个很重要的数据结构,它是Context的具体实现,
* Context中改的大部分逻辑都是由ContextImpl来完成的。
* ContextImpl是通过Activity的attach方法来和Activity建立关联的。
* (3)此外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,
* 这样当Window接收到外部输入事件后就可以将事件传递给Activity。
* */
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
/*
* 第五步:调用Activity的onCreate方法:
* 到此为止,Activity也就完成了整个启动过程,
* */
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getDelegate().onSaveInstanceState(outState);
}
public AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, this);
}
return mDelegate;
}
public static AppCompatDelegate create(Activity activity, AppCompatCallback callback) {
return create(activity, activity.getWindow(), callback);
}
private static AppCompatDelegate create(Context context, Window window,
AppCompatCallback callback) {
final int sdk = Build.VERSION.SDK_INT;
if (sdk >= 23) {
return new AppCompatDelegateImplV23(context, window, callback);
} else if (sdk >= 14) {
return new AppCompatDelegateImplV14(context, window, callback);
} else if (sdk >= 11) {
return new AppCompatDelegateImplV11(context, window, callback);
} else {
return new AppCompatDelegateImplV7(context, window, callback);
}
}
在AppCompatDelegateImplV7中有setContentView方法
@Override
public void setContentView(int resId) {
ensureSubDecor();//获取mSubDeor,是否显示通知栏,actionbar,float等信息
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);//获取content的布局,放我们的布局
contentParent.removeAllViews();
LayoutInflater.from(mContext).inflate(resId, contentParent);
mOriginalWindowCallback.onContentChanged();//window的回调
}
参考:http://blog.csdn.net/zizidemenghanxiao/article/details/50639025