生命周期:1.典型情况下的生命周期 :有用户参与的情况下(当然手机的各种状态都是理想情况下)
2.异常情况下的生命周期:指的是现实情况下,例如手机内容不足。Activity被系统回收,
还有就是当前Configuration发生变化从而导致Activity被销毁重建等。(Actvity在异常情况下,表现十分微妙。)
1.典型情况下的生命周期:如下图所示
如下代码所示:
public classMainActivityextendsAppCompatActivity {
private static finalStringTAG="bill";
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG,"onCreate()");
}
@Override
protected voidonRestart() {
super.onRestart();
Log.d(TAG,"onRestart()");
}
@Override
protected voidonStart() {
super.onStart();
Log.d(TAG,"onStart()");
}
@Override
protected voidonResume() {
super.onResume();
Log.d(TAG,"onResume()");
}
@Override
protected voidonPause() {
super.onPause();
Log.d(TAG,"onPause()");
}
@Override
protected voidonStop() {
super.onStop();
Log.d(TAG,"onStop()");
}
@Override
protected voidonDestroy() {
super.onDestroy();
Log.d(TAG,"onDestroy()");
}
}
上面代码是把activity中所有的生命周期都打印了出来。
那么我们可以看到,第一次启动的时候运行顺序:
以下就不意义列举各种正常情况了:
只写结果:
1.正常情况下,oncreate() onstart() onresume()
2.如果当前activity A打开另一个activity B或点击home键进入桌面,那么此时执行activity A的onpause() onstop()方法,当然此时有一种特殊的activity B是不会调用onstop()方法,只是会调用onpause()方法,那就是,此activity B的主题是透明色的。
3.当回到activity A的时候,调用 onRestart() onstart() onresume()方法
4.当activity被系统回收以后再次打开,生命周期的调用顺序和1是一样的,但是仅仅是生命周期的调用顺序,并不代表其他过程也一样。
5.生命周期配对:oncreate() ondestroy()
onstar() onstop()
onresume() onpause()
那么问题来了:
activity A打开activity B的时候,activity A的onpause()和activity的onResume()方法执行的先后顺序是怎样的?
打印日志可以看出,两个activity调用的生命周期方法,竟然载同一个线程内,如图
从上图可以看出,activity A的onpause()方法先执行,然后执行依次activity B的onCreate() onstart() onResume()方法,再去执行A的onstop()等方法。
另一方面,Android官方也说过,不能在onpause中做一些重量级操作,毕竟要当前的activity先执行完onpause()才能再执行下一个activity的开始生命周期。
2.异常情况下的生命周期
1)资源相关的activity发生改变,导致activity被杀死并重建
例子:资源相关的配置发生改变、系统内存不足的时候,activity可能会被杀死。
在activity下添加以下方法:
@Override
public voidonSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(OUTSTATE,"我被保存下来了");
Log.d(TAG,"Thread :"+ Thread.currentThread() +",onSaveInstanceState()");
}
@Override
public voidonRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if(savedInstanceState !=null) {
String outstate = savedInstanceState.getString(OUTSTATE);
Log.d(TAG,"onRestoreInstanceState() outstates = "+ outstate);
}
Log.d(TAG,"Thread :"+ Thread.currentThread() +",onRestoreInstanceState()");
}
分析:资源相关配置发生改变:
从竖屏转换成横屏的时候,日志如下:
从横屏转换成竖屏的时候,日志如下:
此时知道,我们的activity如果屏幕旋转,会造成生命周期的改变,一般来说是这样:
onpause() -> onsaveinstancestate() -> onstop() -> ondestroy() -> oncreate() -> onstart() -> onrestoreinstancestate() ->onresume()
而且onrestoreinstancestate()能获取到onsaveinstancestate()保存下来的数据,并且调用顺序是在onstart()方法之后。
但是,有一点,日志里边没有说明的:onsaveinstancestate()方法的调用时机是在onstop()之前,而且又和onpause()没有时间顺序上的关系。(待验证)
值得说明的一个是:在执行完activity的onsaveinstancestate()方法之后,还会activity会委托window保存数据,接着window委托他的顶级容器去保存数据,顶层容器是一个viewgroup,然后顶层容器会再去通知他的子元素,例如TextView去调用它的onsaveinstancestate()方法去保存它的数据。这是一个典型的委托思想,在view的绘制过程和分发机制中也是用的类似的思想。
当系统资源内存不足的时候,会由优先级从低到高依次kill activity。
这里的优先级划分:前台展示的activity最高,可见但非前台的activity中级,后台activity优先级最低。(这时候可以根据生命周期是否调用onpause onstop方法判断优先级,例如最高级是没有执行两个方法,中级是之执行了onpause方法,最低级是执行了两个方法)
刚才说的第一种情况,当屏幕的横竖屏改变的时候,activity会重新绘制,会把生命周期先结束再重新开始,那么如果我不想重新绘制activity的话,应该怎么做呢?
答:在manifest给需要设置的activity添加:android:configChanges="orientation",
当然在sdk>13的时候还要加上一个属性scrrenSize,变成:android:configChanges="screenSize|orientation",设置了当前的属性,顾名思义:这个是配置改变的时候,屏幕的横竖配置改变的时候。
并且加上下面的代码:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
switch(newConfig.orientation){
case Configuration.ORIENTATION_LANDSCAPE:
Log.d(TAG,"变成了横着的");
break;
case Configuration.ORIENTATION_PORTRAIT:
Log.d(TAG,"变成了竖着的");
break;
}
}
当屏幕的横竖改变的时候,打印日志为: