Activity生命周期详解

难得过年放假几天,认真看了Android Activity相关的一些资料。解决了以前的好几个疑惑,也比以前对Activity的理解加深了。还是决定把所掌握的浅薄的知识写出来,加深一下印象。如果再能帮到一些刚开始学习Android的人一些帮助,荣幸之至!

废话少说,直接看Activity生命周期及切换的过程图:



onCreate:表示Activity正在被创建,Activity生命周期的第一个方法。一般做一些初始化的工作,比如调用setContentView去加载界面布局资源,初始化Activity所需的数据。(之所以方法名是setContentView,是因为根布局名称叫contentView,上篇博客有讲到。一般我们在onCreate中第一行都会写super.onCreate(savedInstanceState),关于这一行是有什么用,后面会有讲到。)

onRestart:表示Activity正在重新启动。一般情况下,当Activity由不可见状态转化为可见状态时,OnRestart会被调用。 

onStart:表示Activity正在被启动。这个时候我们还看不到,也无法进行交互。

onResume:调用以后表示Activity已可见并可以交互。

onPause:表示当前Activity正在停止,只有当前Activity的onPause执行完以后,新Activity的onResume才可以执行。(注意是onResume才可以执行)

onStop:停止Activity的方法,调用后Activity停止。

onDestroy:表示Activity即将被销毁,Activity生命周期的最后一个回调,一般在这个回调里做一些回收和资源释放的工作。

一般来讲,第一次启动Activity时,会调用 onCreate -> onStart -> onResume 。如果要切换到新的Activity时,则当前Activity回调onPause -> onStop。如果新的Activity是透明主题的,也就是切换到新Activity之后,上一个Activity还能透过透明主题看到,则上一个Activity的onStop不会被调用。这也是onPause和onStop的区别,前者表示已不能交互,但还在前台,后者调用后,Activity已经切换到后台不可见了。 如果又切换回原来的Activity,则回调顺序为 :onRestart -> onStart -> onResume。 当用户按back键回退时,回调顺序为:onPause -> onStop -> onDestroy。 从Activity整个生命周期看,onCreate和onDestroy是配对的,标识着Activity的创建和销毁。onStart和onStop是配对的,标识着Activity的前台和后台的切换。onResume和onPause是配对的,标识着Activity是否可见可交互。

关于切换从Activity A切换到Activity B,要先执行A的onPause 才会执行B的onCreate。官方API里也有说明:When activity B is launched in front of activity A, this callback will be invoked on A. B will not be created until A's onPause() returns, so be sure to not do anything lengthy here.  意思是说A的onPause回调结束后,B的onCreate方法才会被回调。下面是我写的Demo来验证上述结论:

public class MainActivity extends Activity {
    private Button button;
    private static String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
    }

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


public class SecondActivity extends Activity {
    private static String TAG = "SecondActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Log.i(TAG, "====================onCreate");
    }
}

运行后,点击按钮切换到另一个Activity,打印出来的结果:


02-17 17:09:15.605 24060-24060/com.example.gray_dog3.activityblogtest I/MainActivity: =======================onPause

02-17 17:09:15.653 24060-24060/com.example.gray_dog3.activityblogtest I/SecondActivity: ====================onCreate


从日志打印的结果来看,确实如前面所说。当前Activity的onPause执行结束后,才会执行下一个Activity的onCreate。注意,有些情况下我们打开一个Activity可能并没有回调它的onCreate(栈中有它的实例,并且可用),对于这种情况,下一个Activity的onResume一定是在当前Activity的onPause回调结束后才会回调。在源码中也有相关的判断,如果是从Activity A到Activity B,在activityManagerService决定回调一个B的onResume之前会做判断,只有满足A为null或者A的onPause回调结束,B的onResume才会执行。所以一般不要在onPause中执行耗时操作,不然会影响Activity B的显示。而Android中,最好不要做影响UI响应速度的操作,因为这最直接关系到用户体验。

上面分析的是正常情况下Activity的生命周期,下面分析一下异常情况下Activity的生命周期:

有一个很经典的面试题,问Android横竖屏切换时,onResume回调几次,或者问一个Activity从启动中间横竖屏切换了一次,然后销毁,XXX回调了几次。其实这种问题都是在问Activity异常情况下的生命周期。在回答这些问题之前,我们先想一下,Android横竖屏切换时做了什么事,或者说,横竖屏切换时哪些东西发生了改变,怎样改变的。横竖屏切换,首先是整个UI结构要发生改变,其次各个View控件都要重新测量和绘制。所以当我们在回答哪个方法回调之前,首先要知道为什么回调或者为什么不回调。而Android默认的是当横竖屏切换的时候是又重新创建了一次Activity,这个Activity需要执行一个Activity从创建到显示的所有回调。这样,哪个回调调用了几次便不言自明了。最早接触Android的时候看到onCreate中第一行总是:

super.onCreate(savedInstanceState);
而又不知道这一行究竟是什么意思。其实这一行就是和异常情况下Activity生命周期相关的。从字面上看,参数savedInstanceState是保存的实例状态,不好理解。但是我们通常会遇到这样的情况,就是在输入框输入一串字符,如果不小心横竖屏切换了,之前输入的字符还在,或者看电影看到一个节点,横竖屏切换,能在那个点继续播放。这些都是因为输入的字符串或者电影的节点信息保存在savedInstanceState(一个Bundle对象))中。在Activity要被异常终止时,系统都会回调一个方法onSaveInstanceState(),在这个方法中系统会把当前的UI结构以Bundle对象的形式保存下来,并在Activity重启后恢复这些数据,比如文本框输入的内容,ListView滚动的位置等View相关的数据。

此外,系统还提供了一个专门用来恢复这些数据的方法:onRestoreInstanceState()。这个回调和onCreate方法都会判断Activity是否被重建了,如果被重建了,就取出之前保存在Bundle对象中的数据并恢复。从时序上看,onRestoreInstanceState()回调应该在onStart()之后。其实每个View中都有onSaveInstanceState和onRestoreInstanceState这两个方法,而Activity的中的这两个方法正是委托Widow去保存和恢复数据,然后Window再委托顶层容器(一般是DecorView),顶层容器逐级委托下去,到各个子控件,最终是通过这种委托思想来完成的。其实Android中大量使用这种委托思想,比如View的绘制,和事件的分发等,此处不一一列举。

上面说的是Activity异常生命周期的一种情况,即资源相关的系统配置发生改变导致Activity杀死并重建。还有一种情况是由于资源内存不足,导致低优先级的Activity被杀死。这种情况数据存储与恢复和系统配置改变是一样的,不再赘述。下面给出Activity异常情况下的生命周期图:



图中可以看出,当Activity被杀死以后,可以回调onCreate()或者onRestoreInstanceState()方法来恢复Activity。这两种方法究竟有什么区别呢?其实系统默认情况下,Activity是会被重建的,但是我们可以设置,使得由系统资源配置引起的Activity重建不会执行。最常用的由资源相关的系统配置导致的Activity重建的因素有:

项目

含义

locale

切换系统语言

keyboardHidden

键盘的可访问性发生改变,比如用户调出了键盘

orientation

屏幕方向发生改变,旋转手机屏幕

screenSize

屏幕尺寸发生改变,旋转屏幕也会导致屏幕尺寸发生改变,当minSdkVersion和targetSdkVersion均低于13的时候,此选项不会导致Activity重启,否则会导致Activity重启


当这些配置改变的时候,我们只需要在AndroidManifest文件中Activity中加入android:configChanges="orientation|screenSize”   这个属性就可以了,示例:

<activity android:name=".SecondActivity"
    android:configChanges="orientation|screenSize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity>

同样,还有一些不常见的,也都有对应的属性值,用法都是一样的,详情参见:http://developer.android.com/intl/zh-cn/guide/topics/manifest/activity-element.html中的configChanges。这样在对应资源系统配置改变的时候,就不再重新创建Activity,而是回调它的onRestoreInstanceState()方法,官方也推荐使用这种做法。

关于Activity生命周期的细节由于水平有限,暂时就先讲这么多。










  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值