安卓面试题:1 - 关于 activity

5,538
原文链接: www.iwfu.me

Activity的生命周期

Activity生命周期
其中,onCreate和onDestroy一对,分别控制Activity的创建和销毁。onStart和onStop一对,分别控制Activity的可见与不可见,onResume和onPause是一对,控制Activity是否可以与用户交互(是否处于前台)。

当前Activity转到新的Activity界面或按Home键回到主屏: onPause()—>onStop(),进入停滞状态。

onRestart()—>onStart()—>onResume(),再次回到运行状态。

onRestart:表示Activity正在重新启动,一般情况下,当当前Activity由不可见变为可见状态,onRestart就会被调用,比如用户按home回到桌面或者打开了一个新的Activity,然后用户又返回原来的Activity。

Activity退居后台,且系统内存不足, 系统会杀死这个后台状态的Activity(此时这个Activity引用仍然处在任务栈中,只是这个时候引用指向的对象已经为null),若再次回到这个Activity,则会走onCreate()–>onStart()—>onResume()(将重新走一次Activity的初始化生命周期)

锁定屏幕与解锁屏幕 只会调用onPause(),而不会调用onStop()方法,开屏后则调用onResume()
##A activity跳转到B activity时生命周期顺序

A先调用onPause,此时A变成不可交互但任然可见状态,调用onPause后变为不可见状态,然后B调用onCreate-onStart-onResume到可见可交互状态,然后A再调用onStop,完全变为不可见不可交互状态,即将被销毁。

这样是为了方便A activity有足够的时间关闭自己的资源。因为是先调用onPause,所以在onPause里只能执行一些 简单的存储资源,停止动画等。在onStop中做稍微重量级一些的回收工作,但不能太耗时。另一方面我想是为了保证A启动B时intent可以确保到达。

##Activity异常销毁重启时的生命周期和数据的保存

当Activity由于系统配置等发生改变,会导致Activity被杀死而重新创建。即会调用onDestroy销毁Activity,再重新onCreate开启新Activity,系统通过调用onSaveInstanceState和onRestoreInstanceState分别保存和恢复视图(View)状态。

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//这里,当Acivity第一次被创建的时候为空
//所以我们需要判断一下
if( savedInstanceState != null ){
savedInstanceState.getString("anAnt");
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);

outState.putString("anAnt","Android");

}

onSaveInstanceState

onSaveInstanceState在onStop之前调用,但不一定在onPause之前或者之后。onRestoreInstanceState在onStart之后调用

需要注意的是,onSaveInstanceState方法只会在Activity被异常终止,在Activity即将被销毁且有机会重新显示的情况下才会调用

可以总结有下面几种情况


1、当用户按下HOME键时。 这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则 2、长按HOME键,选择运行其他的程序时。 3、按下电源按键(关闭屏幕显示)时。 4、从activity A中启动一个新的activity时。 5、屏幕方向切换时,例如从竖屏切换到横屏时。(如果不指定configchange属性) 在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行

总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。

此外,由于默认的onSaveInstanceState()方法的实现帮助UI存储它的状态,所以如果你需要覆盖这个方法去存储额外的状态信息时,你应该在执行任何代码之前都调用父类的onSaveInstanceState()方法(super.onSaveInstanceState())。 既然有现成的可用,那么我们到底还要不要自己实现onSaveInstanceState()?这得看情况了,如果你自己的派生类中有变量影响到UI,或你程序的行为,当然就要把这个变量也保存了,那么就需要自己实现,否则就不需要。

onRestoreInstanceState

onRestoreInstanceState方法在activity确定被销毁以后,重建activity时调用,注意是确定activity被销毁,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。

另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原。 还有onRestoreInstanceState在onstart之后执行。 至于这两个函数的使用,给出示范代码(留意自定义代码在调用super的前或后):

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "Welcome back to Android");
// etc.
super.onSaveInstanceState(savedInstanceState);
}

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);

boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}

由于内存不足导致的Activity被杀死

当activity由于内存不足,被系统杀死后会调用onSaveInstanceState和onRestoreInstanceState保存和恢复视图。按照优先级从高到低,将activity分为以下三种:

前台Activity
可见但非后台Activity
后台Activity

当系统内存不足,系统会按照上述优先级杀死目标Activity所在进程。

让Activity不随着屏幕旋转而销毁

只需要在manifest的Activity标签添加

android:configChanges="orientation|keyboardHidden"

orientation表示屏幕方向,keyboardHidden键盘可见性(是否调出键盘)。这样在旋转屏幕后activity就不会被销毁重建,不会调用onRestore…和onSave…,而会调用

onConfigurationChanged ()方法。

所以,可以在onConfigurationChanged中保存状态数据。

此外,设置手机屏幕不改变方向:

android:screenOrientation=”landscape” **属性。

landscape = 横向
portrait = 纵向

Activity的启动模式

  • standard 标准模式:
    系统默认模式,每次启动一个activity都会创建一个新的实例压在栈顶,不管这个activity是否已经存在。
  • singleTop 栈顶单例
    如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,所以它的启动三回调就不会执行,同时Activity的onNewIntent()方法会被回调.如果Activity已经存在但是不在栈顶,那么作用于standard模式一样.

  • singleTask 栈内单例
    创建这样的Activity的时候,系统会先确认它所需任务栈已经创建,否则先创建任务栈.然后放入Activity,如果栈中已经有一个Activity实例,那么这个Activity就会被调到栈顶,调用onNewIntent(),并且singleTask会清理在当前Activity上面的所有Activity.(clear top)

  • singleInstance 全局单例
    加强版的singleTask模式,这种模式的Activity只能单独位于一个任务栈内,由于栈内复用的特性,后续请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了

Activity的堆栈管理以ActivityRecord为单位,所有的ActivityRecord都放在一个List里面.可以认为一个ActivityRecord就是一个Activity栈

持续更新,有错误请指出及时改正,缺少的内容后续会以分篇的形式补充~