Android开发艺术1之Activity的生命周期
作为《Android开发艺术探索》这本书的第一篇博客,我就多说几句。本系列博客旨在对书中相关内容进行解读,简化,提供一个入门到提高的流程。不敢说书评,也不能说教程,只希望对有些人有帮助就好,也为了让自己有个巩固的机会!!!
Activity的生命周期,所谓生命周期,就是一个事物从始至终经历的各个阶段,比如一个人的生命周期,就是出身,成年,老去,死亡等,而这每个点都不是自己把控的。Android系统也是如此,一个手机App,给人最直接的就是界面,也就是我们说的activity,当然也叫活动。屏幕上的一个界面从开始到结束以及一些其他情况下都会由系统回调对应的一些方法,具体分为2种情况:正常情况下的生命周期和异常生命周期,这个不懂吗?正常情况下就是由用户参与,比如点击某个按钮进行跳转。而异常情况下就是由于系统资源不足或者横竖屏切换等引起的生命周期自动变化。
一、正常情况下的生命周期 (七个方法)
onCreate 创建
onStart 开始显示,但还未显示出来,其实他主要是与onResume进行区别,个人认为用户是否获取焦点作为区分更好
onResume 表示activity已经可见,其实更准确的说应该是activity可以被用户触摸了,即获取焦点了
onRestart 重新开始显示,一般是activity完全不可见到再次出现,比如按Home键回到桌面,再进入
onPause 暂停,即activity失去焦点,比如一个弹窗出现等
onStop activity正在停止,意义与onStart相对
onDestroy 销毁结束
以上7个生命周期会在正常情况下发生,除了onCreate和onDestroy方法外,其余都可以在用户不同操作下多次出现。其中各种情况就不再多说明,有需要直接去尝试或者上网查阅相关资料
下面说个书中提到的比较精髓的问题:假设当前Activity为A,如果这时用户打开一个新的Activity为B,那么是B的onResume方法和A的onPause方法那个先执行?这个问题也许我们第一印象就能回答出来,但是我们还是按照实事求是的原则,查看源码去寻找准确的结果,具体方法暂时不说(嘿嘿,我也还在学习中),我们也可以直接去看Google提供的API说明:Android官方文档对onPause方法解释中有这么一句,不能在onPause中进行重量级的操作,因为必须onPause执行完成后新的Activity才能Resume!
二、异常情况下的生命周期 (非Exception)
这里主要讲的是横竖屏切换时activity会重新创建,但是这个重新创建不同于上面的,而是通过2个方法的回调onSavaInstanceState和onRestoreInstanceState来进行状态的保存和重现,这里面我们主要来讲解下系统如何进行保存状态以及我们如何来进行额外的信息保存的。
具体当异常情况发生的时候,Activity会被销毁,他的onPause onStop onDestroy都会被回调,同时会在onStop之前调用,具体调用时机与onPause不相上下。当Activity被重现创建后,会回调onRestoreInstanceState,他的回调时机在onStart之后。
下面说说系统为我们做的屏幕快照和恢复工作,异常情况下,系统会为我们保存当前activity的视图结构,并且在重启之后为activity恢复这些结构,比如文本输入框中的输入数据,选中数据,ListVeiw,ScollView当前滑动的位置等,这些都是系统为我们自动完成的,系统的做法实际上是一种代理模式,由Acitivity委托Window去保存数据,Window会委托上面的顶级容器保存数据,定期容器又会一层一层的委托他的子容器或者子控件,达到保存数据状态的效果,其实这跟事件分发,View的绘制过程等一样的原理。下面我们看下TextView源码中的onSavaInstanceState这个方法:
@Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); // Save state if we are forced to boolean save = mFreezesText; int start = 0; int end = 0; if (mText != null) { start = getSelectionStart(); end = getSelectionEnd(); if (start >= 0 || end >= 0) { // Or save state if there is a selection save = true; } } if (save) { SavedState ss = new SavedState(superState); // XXX Should also save the current scroll position! ss.selStart = start; ss.selEnd = end; if (mText instanceof Spanned) { Spannable sp = new SpannableStringBuilder(mText); if (mEditor != null) { removeMisspelledSpans(sp); sp.removeSpan(mEditor.mSuggestionRangeSpan); } ss.text = sp; } else { ss.text = mText.toString(); } if (isFocused() && start >= 0 && end >= 0) { ss.frozenWithFocus = true; } ss.error = getError(); if (mEditor != null) { ss.editorState = mEditor.saveInstanceState(); } return ss; } return superState; }
上面的方法中可以看出,TextView保存了自己的文本内容和选中的文本状态,这些内容在onRestoreInstanceState中会得到使用进行恢复。
接下来我们简单的讲下如何进行我们自己的数据保存呢?首先在我们的onSaveInstanceState方法中有个参数叫Bundle outState, 这个参数就是我们要使用的,他是可以进行数据携带的,我们只需要调用他的存储数据 outState.putString("extra_test" , "test"); 这样就将数据进行了存储,当activity异常销毁的时候会回调这个方法并且将这条数据存储起来,在重现启动时回调onRestoreInstanceState这个方法,他的参数也是Bundle savedInstanceState ,然后进行取出 String test = sacedInstanceState.getString("extra_test"); 就这样完成了。
注意的地方是,如果异常启动的时候 onCreate中也会有Bundle参数传回,同样可以在那里面进行恢复处理,但是由于onCreate方法在正常的情况下传回的Bundle参数为null,所以进行获取的时候需要进行判断,还是建议在onRestoreInstanceState方法中做这些事。
当然屏幕切换时可以禁止activity销毁重启的,只需要在全局配置清单中对应activity标签下加入:android:configChanges = "orientation"即可,此时屏幕旋转将不再销毁重启,也不会回调上述2个方法,但是会回调方法onConfigurationChanged方法,我们可以在这个方法中做相应的处理。注意这里的禁止并不是禁止横竖屏切换,而是当横竖屏切换时我们让activity不重启,如果要进行横竖屏切换禁止的话,需要添加如下参数 android:screenOrientation="portrait" 即可了。
以上就是对Activity的生命周期分析,如有疑问可留言,也可以留下你宝贵的意见。