activity生命周期,启动模式详解

activity生命周期,启动模式详解

  • Activity五个状态
  • Activity的生命周期
  • Activity横竖屏切换生命周期
  • Activity的启动模式
  • Activity的数据保存与恢复

Activity五个状态

Starting(启动状态)->running(运行状态)->paused(暂停状态)->Stopped(停止状态)->Destroyed(销毁状态)
关于activity四个状态的生命周期:
activity生命周期,启动模式详解_第1张图片

  • 启动状态(Starting):Activity的启动状态很短暂,当Activity启动后便会进入运行状态(Running)。
  • 运行状态(Running):Activity在此状态时处于屏幕最前端,它是可见、有焦点的,可以与用户进行交互。如单击、长按等事件。即使出现内存不足的情况,Android也会先销毁栈底的Activity,来确保当前的Activity正常运行。
  • 暂停状态(Paused):在某些情况下,Activity对用户来说仍然可见,但它无法获取焦点,用户对它操作没有没有响应,此时它处于暂停状态。例如,当前Activity弹出Dialog,或者新启动Activity为透明的Activity等情况。
  • 停止状态(Stopped):当Activity完全不可见时,它处于停止状态,但仍然保留着当前的状态和成员信息。如系统内存不足,那么这种状态下的Activity很容易被销毁。
  • 销毁状态(Destroyed):当Activity处于销毁状态时,将被清理出内存。

一些极端情况下,例如系统内存不足,也可能在Paused状态中,直接被系统杀死进入Kill。

Activity的生命周期

activity的生命周期
oncreate()->onstart()->onResume()->onRestart()->onPouse()->onStop()->onDestory()
activity生命周期,启动模式详解_第2张图片
上面图概括了android生命周期的各个环节,描述了activity从生成到销毁的过程。

  • onCreate() : 在Activity创建时调用,通常做一些初始化设置,不可以执行耗时操作。;

  • onNewIntent()*:注意 !!只有当 当前activity实例已经处于任务栈顶,并且使用启动模式为singleTop或者SingleTask再次启动Activity时才会调用此方法。此时不会走OnCreate(),而是会执行onNewIntent()。因为activity不需要创建而是直接复用。

  • onStart(): 在Activity即将可见时调用;可以做一些动画初始化的操作。

  • onRestoreInstanceState()*:注意 !!当app异常退出重建时才会调用此方法。可以在该方法中恢复以保存的数据

  • onResume(): 在Activity已可见,获取焦点开始与用户交互时调用;当Activity第一次启动完成或者当前Activity被遮挡住一部分(进入了onPause())重新回到前台时调用,比如弹窗消失。当onResume()方法执行完毕之后Activity就进入了运行状态。根据官方的建议,此时可以做开启动画和独占设备的操作。

  • onPause(): 在当前Activity被其他Activity覆盖或锁屏时调用;Activity停止但是当前Activity还是处于用户可见状态,比如出现弹窗;在onPause()方法中不能进行耗时操作(当前Activity通过Intent启动另一个Activity时,会先执行当前Activity的onPause()方法,再去执行另一个Activity的生命周期)

  • onSaveInstanceState():注意 !! 只有当app可能会异常销毁时才会调用此方法保存activity数据。以便于activity重建时恢复数据
    Activity的onSaveInstanceState回调时机,取决于app的targetSdkVersion:
    targetSdkVersion低于11的app,onSaveInstanceState方法会在Activity.onPause之前回调;
    targetSdkVersion低于28的app,则会在onStop之前回调;
    28之后,onSaveInstanceState在onStop回调之后才回调。

  • onStop() : 在Activity完全被遮挡对用户不可见时调用(在onStop()中做一些回收资源的操作)

  • onDestroy() :在Activity销毁时调用;

  • onRestart() : 在Activity从停止状态再次启动时调用;处于stop()状态也就是完全不可见的Activity重新回到前台时调用(重新回到前台不会调用onCreate()方法,因为此时Activity还未销毁)

Activity横竖屏切换生命周期

横竖屏切换涉及到的是Activity的android:configChanges属性;
android:configChanges可以设置的属性值有:

  • orientation:消除横竖屏的影响
  • keyboardHidden:消除键盘的影响
  • screenSize:消除屏幕大小的影响
public class MainActivity extends AppCompatActivity {
public static final String TAG=MainActivity;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.i(TAG,"onCreate");
    setContentView(R.layout.activity_main);
}

@Override
protected void onStart() {
    super.onStart();
    Log.i(TAG,"onStart");
}

@Override
protected void onResume() {
    super.onResume();
    Log.i(TAG,"onResume.........");
}

@Override
protected void onPause() {
    super.onPause();
    Log.i(TAG,"onPause");
}

@Override
protected void onStop() {
    super.onStop();
    Log.i(TAG,"onStop");
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.i(TAG,"onDestroy");
}

启动activity,生命周期如下:
onCreate()->onStart()->onResume()
切换横屏,生命周期如下:
onPause()->onStop()->onSaveInstanceState()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()
再切换为竖屏,生命周期如下:
onPause()->onStop()->onSaveInstanceState()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()
修改AndroidManifest.xml,添加android:configChanges="orientation"并切换横屏,生命周期如下:
onPause()->onStop()->onSaveInstanceState()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()
再切换竖屏,生命周期如下:
onPause()->onStop()->onSaveInstanceState()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState()->onResume()
修改AndroidManifest.xml,属性改为android:configChanges=“orientation|keyboardHidden|screenSize”,切换横屏,生命周期如下:
onConfigurationChanged()
再切换回竖屏,生命周期如下:
onConfigurationChanged()

结论

设置Activity的android:configChanges属性为orientation或者orientation|keyboardHidden或者不设置这个属性的时候,横竖屏切换会重新调用各个生命周期方法,切横屏时会执行1次,切竖屏时会执行1次;
设置Activity的属性为android:configChanges="orientation|keyboardHidden|screenSize"时,横竖屏切换不会重新调用各个生命周期方法,只会执行onConfigurationChanged方法;

Activity的启动模式

一个项目中会包含多个activity,系统中使用任务栈来存储这些activity,任务栈呢,是一种“后进先出”的栈结构。举个栗子:当我们多次启动同一个(没有设置启动方式–即默认的启动方式)的activity的时候,系统会创建多个实例依次进入栈中。当back返回的时候,每按一次,一个activity出栈。直至栈空为止。
activity生命周期,启动模式详解_第3张图片

  • Standard 标准模式

无论任务栈内是否已经存在要启动的Activity实列,都会创建一个Activity放入任务栈,并置于栈顶。
使用场景:默认使用大多数场景

  • SingleTop栈顶复用模式

如果任务栈顶部已经存在一个要启动的Activity实列,就复用该Activity不会重新创建Activity的实列,复用Activity会执行onNewIntent方法,但是onCreate.onStart方法不会执行,因为它没有改变。如果任务栈顶没有实例就创建一个Activity实例存入其中,置于栈顶。

使用场景:适合接收通知内容显示页面,当用户从任务栏中进入查看消息内容界面时,如果设置为singleTop时,这样每次行为都使用同一个实例,用户点击返回时不会存在多个消息页面的情况。

  • SingleTask栈内复用模式

如果栈内已经存在要启动的Activity实例,就把该Activity栈上面的activity清出栈,让该activity置于栈顶,如果复用它的onNewIntent方法会被回调,但是onCreate方法不会执行,因为它没有改变.
使用场景:APP的首页,当你需要到某个页面时,关闭之前所打开的Activity可以用到。

SingleInstance单实例模式

这种模式启动的Activity实例单独占用一个任务栈,也就是启动该模式的Activity同时给它分配一个任务栈。

使用场景:singleInstance适合需要与程序分离开的页面。例如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。

Activity的数据保存与恢复

只有当Activity在异常状态下被结束时,系统才会调用onSaveInstanceState()方法,用于保存当前Activity的状态,以便后续在重建被异常结束的Activity时调用onSaveInstanceState()方法来恢复现场。

onSaveInstanceState()方法只在Activity被异常结束的时候调用,而且是在onStop之前。onSaveInstance方法会把数据保存在Bundle对象中,当被异常结束的Activity被重建以后,系统会调用onRestoreInstanceState方法,并把这个Bundle对象同时传递给onRestoreInstanceState和onCreate方法。因此onRestoreInstanceState方法可以用于恢复Activity的状态。onRestoreInstanceState方法的调用时机是在onStart之后。

那么,具体来说onSaveInstance方法会在什么时候被调用呢?

上面我也提到onSaveInstance方法是在onstop之前执行,也就是用户切换到桌面或者别的应用的时候就会被调用。onSaveInstance方法只在Activity被异常结束的时候调用,其实就是说当你的应用有可能被异常结束的时候,这个方法就会被调用。

下面这些都是应用有可能被异常结束的情况,这种时候系统就会调用onSaveInstance:

1、用户按home键切换到桌面

2、切换到别的应用

3、按下电源按钮/息屏

4、横竖屏切换

横竖屏切换的生命周期:onPause()->onSaveInstanceState()->onStop()->onDestroy()->onCreate()->onStart()->onRestoreInstanceState->onResume()

可以看出来横竖屏切换的时候经历了Activity的销毁和重建。如果我们不希望横竖屏导致Activity的销毁和重建,我们可以这样做:

在AndroidManifest文件的Activity中指定如下属性:

android:configChanges = "orientation| screenSize"

这样的话当应用进行横竖屏切换的时候,就不会经历Activity的销毁和重建了,而是回调以下方法:

@Override
public void onConfigurationChanged(Configuration newConfig){
    super.onConfigurationChanged(newConfig);
}

onRestoreInstatnceState()方法用于Activity被异常结束后再次创建的时候调用来恢复现场。但是需要注意的是,onRestoreInstanceState()方法不一定是和onSaveInstanceState()方法成对出现的。
onSaveInstanceState()方法是在系统判断Activity有可能被异常结束的时候就会被调用,而onRestoreInstanceState()方法则是必须要Activity真的被异常销毁之后并重建的时候才能调用。
比如用户先在Activity a中切换到Activity b,然后马上又返回到Activity a,因为从a切换到b的时候,系统判断为有可能会被异常销毁,所以会调用onSaveInstanceState()方法,但是因为Activity没有真正被销毁,所以从Activity b返回到Activity a的时候,Activity a不会调用onRestoreInstanceState()。onRestoreInstanceState()的调用基于Activity真的被异常销毁这个事实上。

另外,因为调用onSaveInstanceState()方法保存的Bundle对象会同时传递给onCreate()和onRestoreInstanceState()方法,所以也可以在onCreate()方法中进行恢复数据的操作。onCreate()和onRestoreInstanceState()方法恢复Activity的区别在于:

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    initView()
    BaseApplication.getApplication().startService(WebSocketConnectServer::class.java)
  }

  override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
  }

  override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
  }

onRestoreInstanceState()回调则表明Bundle对象非空,不用加非空判断,而onCreate()中则需要非空判断,因此一般建议使用onRestoreInstanceState()方法来进行数据恢复。

你可能感兴趣的:(android)