首先我们需要知道Activity的管理原理——Task,一个Task一组存放在栈里的Activity的集合,栈的工作原理是先进后出,后进先出,即新创建的Activity会在栈顶,销毁后弹出,下一个Activity弹到栈顶,以此类推直到无Activity可销毁。
Activity状态
在一个Activity中最多有四种生命周期
-
运行状态:处于栈顶时
-
暂停状态:不处于栈顶但仍然可见时
-
停止状态:不处于栈顶但是不可见
-
销毁状态:弹出
Activity的生存期
Activity中有七个回调方法。下面一一介绍
-
onCreate ,在这个方法里应该完成初始化操作,比如加载布局、绑定事件
-
onStart ,在Activity由不可见变为可见调用
-
onResume, 这个方法在Activity准备和用户进行交互时调用,此时Activity一定是运行状态。
-
onPause,用于准备去启动或者回复另一个Activity时调用,通常用于将一些消耗的CPU给释放掉
-
onStop,与onPause,的区别在于,一个是可见时调用(onPause),另一个是不可见时调用(onStop)
-
onDestroy,显而易见,销毁之前调用
-
onRestart,由停止到运行调用
以上除了onRestart,其余的两两相对,又可以将Activity分为以下生存期
-
完整生存期:onCreate到onDestroy之间
-
可见生存期:onStart到onStop之间
-
前台生存期:onResume到onPause之间,总是处于运行状态
体验Avtivity的生命周期
为了更清晰的理解生存期的更替,我重写了onCreate/onStart…方法,在方法体打印信息。如下
override fun onStart() {
super.onStart()
Log.d(tag,"onStart")
}
再布局两个按钮Button,一个启动NormalActivity,另一个启动DialogActivity,从名字上可以看出,一个是普通的,一个是对话框,这里需要设置对话框。
设置对话框
在AndroidManifest中,只需在所需要设置对话框的Activity里设置style即可
<activity
android:name=".DialogActivity"
android:exported="false"
android:theme="@style/Theme.AppCompat.Dialog"/>
</>
这里的style可以选择多种,Dialog便是对话框主题。
先看一下运行效果
-
这是布局

-
对话框的形式出现

-
以普通的文本形式出现

在这里为什么要进行对比呢,我们其实可以观察到,当激活对话框,MainActivity是没有被遮盖,MainActivity则是可见的,另一种普通文本,MainActivity会被遮盖,变成不可见形式,分别对应onPause和onStop,查看日志可得到验证。
启动MainActivity时,依次执行

点击Start NormalActivity

依次调用了onPause和onStop
点击Back键后执行reStart,后点击Start DialogActivity

可以看到,只执行了onPause,并没有执行onStop。最终销毁则是执行onDestroy。
Activity被回收怎么办
被回收是什么情况?当一个Activity停止太久后,系统由于内存不足会清理掉。假设我们由Activity_A启动Activity_B,而后Activity_A被回收掉,这时候点击Back从Activity_B返回会怎么样呢?实际上不会怎么样,而是正常运作Activity_A,但是,
返回时并不是执行onRestrt方法,而是执行Activity_A的onCreate方法,相当于重新初始化了,这时候就会出现问题,会丢失临时数据。
这时候应该怎么解决呢?
Activity其实提供了一个onSaveInstanceState方法,此方法在回调前一定会被调用,因此就可以利用它解决问题!
onsaveInstanceState()的参数是一个Bundle参数,用于保存各种数据,比如putString(key,data),key是用于后面方便找回信息,若是Int类型则有putInt()
只需在MainActivity中编写即可。
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val temp = "I LOVE YOU"
outState.putString("data_key",temp)
}
保存后的数据我们可以从onCreate的参数中获取,因为它也是Bundle类型,若没有保存数据,则为空,简单做一个if判断即可
if (savedInstanceState!=null)
{
val saved = savedInstanceState.getString("data_key")
Log.d(tag,"tempData is $saved")
}