本篇总结关于activity相关的面试内容。
生命周期
首先来看一下官网上面的关于activity的生命周期的图。
首先新建两个activity,MainActivity和BActivity,第一个activity可以跳转到BActivity,然后观察它们之间的生命周期的log
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
KLog.d("MainActivity ----------> onCreate");
}
public void onClickBtn(View view) {
KLog.d("MainActivity ----------> onClickBtn");
switch (view.getId()) {
//跳转到BActivity
case R.id.button:
startActivity(new Intent(MainActivity.this, BActivity.class));
break;
}
}
@Override
protected void on Start() {
super.on Start();
KLog.d("MainActivity ----------> on Start");
}
@Override
protected void onResume() {
super.onResume();
KLog.d("MainActivity ----------> onResume");
}
@Override
protected void onPause() {
super.onPause();
KLog.d("MainActivity ----------> onPause");
}
@Override
protected void on Stop() {
super.on Stop();
KLog.d("MainActivity ----------> on Stop");
}
@Override
protected void onDestroy() {
super.onDestroy();
KLog.d("MainActivity ----------> onDestroy");
}
@Override
protected void onRestart() {
super.onRestart();
KLog.d("MainActivity ----------> onRestart");
}
}
启动MainActivity
Log打印出为onCreate——>on Start——>onResume
跳转到BActivity
Log打印出为onPause(MainActivity)——>onCreate(BActivity)——>on Start(BActivity)——>onResume(BActivity) ——> on Stop(MainActivity)
BActivity锁屏
Log打印出为onPause——>on Stop
BActivity解锁显示
Log打印出为onRestart——>on Start——>onResume
BActivity退回到MainActivity
Log打印出为onPause(BActivity)——>onRestart(MainActivity)——>on Start(MainActivity)——>onResume(MainActivity) ——> on Stop(BActivity)——>onDestroy(BActivity)
按home键
Log打印出为onPause——>on Stop
再次进入MainActivity
Log打印出为onRestart——>on Start——>onResume
可以看出来,锁屏和按home键,显示生命周期是一样的。
退出MainActivity
Log打印出为onPause——>on Stop——>onDestroy
以上便是一个完整的生命周期图,当然了其中还有可能包括:正好来电话了、、、、等生命周期。
横竖屏切换
当我们进行横竖屏切换时,相应的activity会销毁并进行重建操作。
启动MainActivity(竖屏)
Log打印出为onCreate——>on Start——>onResume
然后进行横屏显示
可以很清楚地看到了activity销毁并重建了,但是在重建过程中会调用onRestoreInstanceState进行恢复数据操作。所以为了不必要的麻烦,我们可以设置只显示竖屏或者横屏
通过在AndroidManifest.xml中设置activity中的android:screenOrientation属性值来实现。
android:screenOrientation="portrait"
则无论手机如何变动,拥有这个属性的activity都将是竖屏显示。
android:screenOrientation="landscape",为横屏显示。
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
另外,android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置,那样,进行中的游戏就不会自动重启了!
onSaveInstanceState和onRestoreInstanceState 是一对兄弟,一个负责存储,一个负责取出.“不一定”是成对的被调用的。
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
http://www.cnblogs.com/hanyonglu/archive/2012/03/28/2420515.html
关于生命周期注意事项
- 如果一个Activity在用户可见时才处理某个广播,不可见时注销掉,那么应该在哪两个生命周期的回调方法去注册和注销BroadcastReceiver呢?
Activity 的可见生命周期发生在 on Start调用与 on Stop调用之间。在这段时间,用户可以在屏幕上看到 Activity 并与其交互。我们可以在 on Start中注册一个 BroadcastReceiver以监控影响 UI 的变化,并在用户无法再看到您显示的内容时在 on Stop中将其取消注册。
- 如果有一些数据在Activity跳转时(或者离开时)要保存到数据库,那么你认为是在onPause好还是在on Stop执行这个操作好呢?
onPause较容易被触发,所以我们在做BroadcastReceiver注销时放在on Stop要好些。onPause时Activity界面仍然是可见的,如弹出一个Dialog时。但在保存数据时,放在onPause去做可以保证数据存储的有效性,如果放在on Stop去做,在某些情况下Activity走完onPause后有可能还没顺利走到on Stop就被系统回收了。
参考链接: http://www.jianshu.com/p/ae6e1d93cc8e
启动模式
四种启动模式,standard, singleTask, singleTop, singleInstance。
- standard: 标准模式,在当前的任务栈上创建新的Activity,不论之前有没有创建过该Activity。
- singleTask: 栈内复用模式,分两种情况,第一种情况:如果有任务栈里已经创建了该Acitiviy,直接销毁该Acitivity栈上面的所有Acitivity,无须新创建一个Activity;第二种情况:如果没有任务栈里已经创建该Activity,创建一个新的任务栈并在新栈上创建新Activity。注意:该模式下复用Activity,系统会调用Activity的onNewIntent方法。
- singleTop: 栈顶复用模式,如果该Activity在任务栈栈顶,即当前活动的Acitivty就是要创建的Activity,那么不会创建新的Activity。注意:该模式下复用Activity,系统会调用Activity的onNewIntent方法。
-
singleInstance:单实例模式,加强版的singleTask,当每次都直接创建一个新的任务栈,再在该新栈上创建新Activity。注意:singleInstance永远是单栈单Activity
与之对应的是IntentFlag的设置,同样也能达到效果:
Intent Flag描述启动模式
Flags:
表示Intent的标志位,常用于Activity的场景中,它和Activity的启动模式有着密切的联系,简单说,flag的有效组合(通常用“|“组合使用)决定如何打开Activity。
- Intent.FLAG_ACTIVITY_NEW_TASK (默认) 默认的跳转类型,它会重新创建一个新的Activity。
- FLAG_ACTIVITY_SINGLE_TOP 这个FLAG就相当于启动模式中的singletop,请参考singletop说明。
- FLAG_ACTIVITY_CLEAR_TOP
这个FLAG启动的Activity会把要启动的Activity之上(包含自身)的Activity全部弹出栈空间。例如:原来栈中的结构是A B C D ,从D中跳转到B,释放顺序为D C B,然后重新创建B置于栈顶,栈中的结构就变为了A B了。(这个方法可以用来关闭多个Activity)
经验:需要销毁栈中A之前的多个activity,但并不想销毁A,就需要FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_SINGLE_TOP组合使用 - FLAG_ACTIVITY_CLEAR_TASK 这个Flag使用的前置条件为:API level 11 以上版本,并且需要与FLAG_ACTIVITY_NEW_TASK一起使用。此标识,用于释放当前栈中所有的activity,然后再创建新的Activity对象置于栈顶。 例如栈中原有A B C D,需要从D跳转到B,依次释放D C B A,然后创建B,置于栈顶。