Android Activity生命周期

Android生命周期

Android的生命周期:onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy() 以下图所示:android

  1. 1.当activity启动时系统会先调用onCreate(),而后调用onStart(),最后调用**onResume()**方法,activity进入运行状态。
  2. 当activity被别的activity 覆盖在其上时:系统会掉用onPause(),而后当覆盖在其上的activity会调用**onCreate() -> onStart() -> onResume()后,第一个activity会调用onStop()**方法使activity暂停。
  3. 当覆盖在其上的第二个activity关闭返回此activity时,系统会先调用第二个activity的**onPause()方法而后再调用第一个activity的onRestart() -> onStart() -> onResume()方法,进入运行状态,此时第二个activity才调用onStop() -> onDestroy()**方法关闭。
  4. 用户退出当前activity:系统先调用onPause(),而后调用onSotp(),最后调用**onDestroy()**方法,结束当前activity。

以下日志打印 第一个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

  • 状况1:资源相关配置方式改变致使activity被杀死并从新建立。 好比当前activity处于竖屏,旋转屏幕,这时因为activity的系统配置改成了横屏状态,在默认状况下,activity就会被销毁而且从新建立,日志打印以下:
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按照优先级从高到低能够分为如下三种:

    1. 前台activity:正在和用户交互的activity,优先级最高。 2.可见可是非前台activity:就是能看见,可是没有获取到焦点不能和用户进行直接交互。 3.后台activity:已经被暂停的activity,好比执行了onStop()方法,优先级最低。

注意: 必须始终调用 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()方法中将每一个资源从新分配给每一个元素。
    复制代码

这个例子代码在这里