Android的生命周期:onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy() 以下图所示:android
以下日志打印 第一个activity MainActivity 打开 SingleTopActivity 在返回到 MainActivitygit
MainActivity :onPause 方法-------------------------
SingleTopActivity :onCreate 方法-------------------------
SingleTopActivity :onStart 方法-------------------------
SingleTopActivity :onResume 方法-------------------------
MainActivity :onSaveInstanceState 方法--------------------
MainActivity :onStop 方法-------------------------
SingleTopActivity :onPause 方法-------------------------
MainActivity :onRestart 方法-------------------------
MainActivity :onStart 方法-------------------------
MainActivity :onResume 方法-------------------------
SingleTopActivity :onStop 方法-------------------------
SingleTopActivity :onDestroy 方法-------------------------
复制代码
onRestart():表示activity正在从新启动,通常状况下是当前activity从不可见从新变成可见状态时,**onRestart()**就会被调用,这种状况通常是用户行为致使的,如从其余页面返回当前页面时,或者用户按home键切换到桌面在从新打开app。github
onStart()和onStop():onStart()表示activity可见了,可是尚未获取焦点,没法进行交互。onStop()是和onStart()对应的当activity从可见转不可见是调用。app
onResume()和onPause():onResume()表示activity已经获取焦点了,能够进行交互了,onPause()是和onResume()方法对应的表示当前activity失去了焦点,此时能够作一些存储数据和中止动画等工做,可是不能太好时,不是会影响到新的activity的显示,由于只有onPause()执行完了,新的activity才会进入 onCreate() 等方法。ide
onDestroy():onDestroy()表示activity正在销毁,通常咱们是在这进行资源的释放,以免内存的泄漏。动画
注意:this
- 若是覆盖在其上的activity的风格是dialog风格的化,此activity是不会进入**onSotp()**方法,回到此activity时也**不会调用onRestart()和onStart()方法** 会直接调用**onResume()**方法。
- 若是activity中弹出dialog对话框的时候,**activity是不会调用onPause()方法**;
- 只有旧的activity onPause()方法执行完后,新的activity才启动
- 在因此状况下,系统在调用了onPause()和onStop()以后都会调用onDestroy(),只有一个例外:当你从onCreate()方法类调用了finish()时,在这种状况下,系统会马上调用onDestroy(),而不调用任何其余生命周期方法。日志以下:
复制代码
MainActivity :onPause 方法-------------------------
DialogActivity :onCreate 方法-------------------------
MainActivity :onResume 方法-------------------------
DialogActivity :onDestroy 方法-------------------------
复制代码
异常状况下的生命周期:好比系统资源配置发生改变以及系统内存不足时,activity就可能被杀死。spa
MainActivity :onCreate 方法-------------------------
MainActivity :onCreate:MainActivity TaskId:130 hasCode:151566767
MainActivity :onStart 方法-------------------------
MainActivity :onResume 方法-------------------------
MainActivity :onPause 方法-------------------------
MainActivity :onSaveInstanceState 方法-------------------------
MainActivity :onStop 方法-------------------------
MainActivity :onDestroy 方法-------------------------
MainActivity :onCreate 方法-------------------------
MainActivity :onCreate:MainActivity TaskId:130 hasCode:233659052
MainActivity :onStart 方法-------------------------
MainActivity :onRestoreInstanceState 方法-------------------------
MainActivity :onResume 方法-------------------------
MainActivity :onPause 方法-------------------------
MainActivity :onSaveInstanceState 方法-------------------------
MainActivity :onStop 方法-------------------------
MainActivity :onDestroy 方法-------------------------
MainActivity :onCreate 方法-------------------------
MainActivity :onCreate:MainActivity TaskId:130 hasCode:262962597
MainActivity:TaskAffinity:com.hugo.reviewbasic
MainActivity :onStart 方法-------------------------
MainActivity :onRestoreInstanceState 方法-------------------------
MainActivity :onResume 方法-------------------------
复制代码
在上面这日志中 咱们进入MainActivity -> onCreate() -> onStart () -> onResume() 这个时候MainActivity已经在栈顶并得到焦点了,而后咱们旋转手机屏幕,3d
这时调用了 onPause() -> onSaveInstanceState() -> onStop() - onDestroy() 方法把当前MainActivity 销毁了,而后紧接着又从新建立了一个MainActivity -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()日志
这是MainActivity已经从新建立而且是横屏显示的,这是咱们又旋转手机屏幕从新竖屏显示 ,这是调用了 onPause() -> onSaveInstanceState() -> onStop() - onDestroy() 方法把当前横屏MainActivity 销毁了,并从新建立了竖屏的MainActivity -> onCreate() -> onStart() -> onRestoreInstanceState() -> onResume()
在这上面的流程咱们能够看到 在第一次进入MainActivity 时是每有调用onRestoreInstanceState() 方法的而是在从新建立时才调用了该方法,这个方法是用来作什么的呢?这个方法就是用来在activity被销毁并从新建立时用来恢复咱们保存的数据用的,那咱们的数据在哪保存的呢,能够看到日志里每次在销毁前都有调用 onSaveInstanceState() 方法,这个方法就是用来保存数据用的。
在onSaveInstanceState()方法中系统会传入Bundle对象用来存储数据,在从新建立时onRestoreInstanceState()方法系统会传入在onSaveInstanceState()方法是存储了数据的Bundle对象,在onRestoreInstanceState()方法里能够在传入的Bundle对象中获取存储的数据进行页面恢复。
根据日志能够看出 onSaveInstanceState() 老是在 onStop()以前调用,而onRestoreInstanceState() 老是在onStart() 以后调用,并且onRestoreInstanceState()在activity第一次建立时是不会调用的。
状况2:在资源不足的状况下致使低优先级的activity被杀死。 这种状况下和前面第一种状况1的数据存储和恢复是彻底一致的,activity按照优先级从高到低能够分为如下三种:
注意: 必须始终调用 onSaveInstanceState()和onRestoreInstanceState() 的超类实现由于这两个方法默认实现了保存有关activity视图层次的状态信息和恢复视图层次结构状态,列如EditText小部件的文本或ListView的滚动位置。并且全部的View都有onSaveInstanceState()和onRestoreInstanceState()这两个方法。
自行处理配置变动: 咱们能够在声明Activity将自行处理配置变动,这样就能够阻止系统重启activity了。 声明时在AndroidManifest.xml文件中编辑相应的""元素,设置以包含的 android:configChanges 属性(最经常使用的值包括“orientation”和“keyboardHidden”,分别用于避免因屏幕方向和可用键盘改变而致使的重启)。咱们能够在该属性中声明多个匹配值,方法是用“ | ”字符分隔这些配置值。 以下配置:
<activity android:name=".singletop.OtherTopActiivty" android:configChanges="orientation|screenSize" android:launchMode="singleTop"/>
复制代码
如今,当其中一个配置发生改变是OtherTopActiivty不会重启,可是OtherTopActiivty的onConfigurationChanged()方法会被调用,系统会 传入Configuration对象指定新的设备配置。咱们能够经过读Configuration中的字段,来肯定新配置,进行相应的UI更改。 如下是在onConfigurationChanged()实现检查当前设备的方向:
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
LogUtil.i(TAG,"$ActivityName :onConfigurationChanged 方法-------------------------")
if(newConfig?.orientation == Configuration.ORIENTATION_LANDSCAPE){
LogUtil.i(TAG,"$ActivityName :onConfigurationChanged 横屏")
Toast.makeText(this,"横屏",Toast.LENGTH_SHORT).show()
}else if(newConfig?.orientation == Configuration.ORIENTATION_PORTRAIT){
LogUtil.i(TAG,"$ActivityName :onConfigurationChanged 竖屏")
Toast.makeText(this,"竖屏",Toast.LENGTH_SHORT).show()
}
}
复制代码
注意:
自行处理配置变动可能致使备用资源的使用更为困难,由于系统不会自动应用这些资源。因此只有在咱们必须避免activity因配置改变而重启这种状况下,才考虑采用自行处理配置变动这种方法,并且对于大多数应用并不建议使用此方法。
复制代码
在Android3.0(API 级别13)开始,设备在纵向和横向之间切换时,“屏幕尺寸”也会发生改变,所以在开发针对API级别13或更高版本的应用时,若要避免因为设备方向的改变而致使运行时重启,则除了“orientation”值外,还必须添加“screenSize“值。也就是必须声明android:configChanges="orientation|screenSize"。
复制代码
在声明有Activity处理配置变动时,咱们有责任要为其提供备用资源的全部元素。如声明了activity处理方向变动,有些图像是应该横向和纵向之间切换,则必须在 onConfigurationChanged()方法中将每一个资源从新分配给每一个元素。
复制代码
这个例子代码在这里