一、Activity生命周期方法:
onCreate():表示Activity刚被创建,会在此方法中使用一些初始化数据操作,以及调用setContentView去加载Activity的布局。
onStart():表示Activity正在被启动,即将开始,这时候的Activity以及变得可见了,只是还不可以和用户进行交互。
onResume():表示Activity出现在前台,并且以及可以和用户进行交互。
onPause():表示Activity正在停止,由可见变为不可见的一个过程,紧接着,onStop方法会被调用。
onStop():表示Activity被停止,出于后台,可以做一些稍微重量级的数据回收,但不可做耗时操作。
onDestory():表示Activity被销毁,这是Activity的最后一个生命周期,可以这里做一些最后的资源回收,以及释放工作。
onRestart():表示Activity正在重新启动,紧接着会调用onStart()。
二、常见异常情况下Activity的生命周期,及数据保存
1、当Activity进行横竖屏切换的时候,当从竖屏切换到横屏
03-26 18:38:12.727 29363-29363/com.kevenzheng E/keven: onPause()
03-26 18:38:12.727 29363-29363/com.kevenzheng E/keven: onStop()
03-26 18:38:12.727 29363-29363/com.kevenzheng E/keven: onDestory()
03-26 18:38:12.797 29363-29363/com.kevenzheng E/keven: onCreate()
03-26 18:38:12.797 29363-29363/com.kevenzheng E/keven: onStart()
03-26 18:38:12.797 29363-29363/com.kevenzheng E/keven: onRestoreInstanceState()
03-26 18:38:12.797 29363-29363/com.kevenzheng E/keven: onResume()
当Activity进行横竖屏切换的时候,当从横屏切换到竖屏:
03-26 18:43:36.057 29363-29363/com.kevenzheng E/keven: onPause()
03-26 18:43:36.057 29363-29363/com.kevenzheng E/keven: onStop()
03-26 18:43:36.057 29363-29363/com.kevenzheng E/keven: onDestory()
03-26 18:43:36.147 29363-29363/com.kevenzheng E/keven: onCreate()
03-26 18:43:36.147 29363-29363/com.kevenzheng E/keven: onStart()
03-26 18:43:36.147 29363-29363/com.kevenzheng E/keven: onRestoreInstanceState()
03-26 18:43:36.147 29363-29363/com.kevenzheng E/keven: onResume()
03-26 18:44:00.227 29363-29363/com.kevenzheng E/keven: onPause()
03-26 18:44:00.227 29363-29363/com.kevenzheng E/keven: onStop()
03-26 18:44:00.227 29363-29363/com.kevenzheng E/keven: onDestory()
03-26 18:44:00.297 29363-29363/com.kevenzheng E/keven: onCreate()
03-26 18:44:00.297 29363-29363/com.kevenzheng E/keven: onStart()
03-26 18:44:00.297 29363-29363/com.kevenzheng E/keven: onRestoreInstanceState()
03-26 18:44:00.297 29363-29363/com.kevenzheng E/keven: onResume()
从上面可以看出,当从竖屏切换为横屏的时候,生命周期重新走了一遍,当从横屏切换为竖屏的时候,整个生命周期运行了两遍。
总结:
(1)不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
(2)设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
(3)设置Activity的android:configChanges="orientation|screenSize"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。(执行这个方法,必须设置sdk version 大于等于13.0)
image.png
2、当Activity在后台被GC回收
会调用onSaveInstanceState()进行数据保存,当Activity重新启动的时候,会调用onRestoreInstanceState()进行数据的恢复工作,需要强调的一点是,只有当Activity是异常结束的时候,才会调用onSaveInstanceState()方法进行数据保存。
三、Activity的四种启动模式
在默认情况下,当我们多次启动同一个Activity,系统会重复创建Activity并压入栈顶,任务栈是个“后进先出”的栈结构,每次都创建同一个Activity的实例难免有些问题,所以安卓提供了四种启动模式:standard、singleTop、singleTask和singleInstance,下面先介绍下四种启动模式:
(1)standard
标准启动模式,每启动一个Activity都会创建一个新的Activity的实例,standard模式启动的Activity默认会进入到启动它的Activity的任务栈中。
(2)singleTop
栈顶复用模式,在这种模式下,如果新的Activity已经存在于栈顶,那么将不会创建此Activity的实例,位于栈顶的Activity将会被复用,并调用onNewIntent方法用于接受当前的请求信息,如果新的Activity并不位于栈顶,那么新的Activity还是会被创建。
(3)singleTask
栈内复用模式,如果要启动的Activity已经存在实例在任务栈中,则不会创建新的Activity实例,且会像singleTop一样,调用onNewIntent方法,用于接受当前的请求信息,如果此Activity位于栈顶,则可以直接复用,如果此Activity不是位于栈顶,则位于此Activity上的所有Activity都会出栈,且复用此Activity的实例。
(4)singleInstance
单例模式,如果要创建的Activity已经存在,则不会创建新的Activity,否则,则创建一个新的任务栈,并将Activity的实例放入任务栈中。单例模式除了具备singleTask模式的所有特性外,还有一点就是单独位于一个任务栈中。
那么怎么给Activity指定启动模式呢?具体有两种方法,一种是通过AndroidManifest为Activity指定启动模式
<activity android:name=".ActivityDemoActivity"
android:launchMode="standard"
>
另一种是通过在Intent中设置标志位来为Activity设置启动模式
Intent intent=new Intent(this,ActivityDemoActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
四、Activity的启动原理(分析源码)
首先说下setContentView方法,进行设置布局,通过查看源码:
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
发现调用了getDelegate的方法,getDelegate方法通过单例模式返回一个AppCompatDelegate对象
@NonNull
public AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, this);
}
return mDelegate;
}
AppCompatDelegate是个抽象类,通过它的setContentView方法进行布局的绑定。
我们都知道,调用startActivity可以启动一个新的Activity,那么究竟是如何启动的呢?
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@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);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
通过上面的代码,我们会发现,调用startActivity的时候,还是调用了startActivityForResult方法,那我们看下startActivityForResult内部的实现:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
其中Instrumentation的execStartActivity方法启动Activity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String resultWho,
Intent intent, int requestCode, Bundle options, UserHandle user) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivityAsUser(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, resultWho,
requestCode, 0, null, options, user.getIdentifier());
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
通过查看源码,发现调用的是ActivityManager.getService().startActivityAsUser,而启动的返回则是调用了
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
网友评论