当android应用程序在运行时,如果系统配置改变,你的应用应相应的做出改变(比如设备转动90度,横屏竖屏等)。ui元素也就需要重新布局,大小重新设定以适应新的配置。
在android中,一个新的配置响应会把当前的activity消掉然后重新创建一个新的。应用程序保持着运行,但api提供了一些方法让activity做出一些动作。给用户一个很好的无缝的用户体验。
一、配置改变的过程
android系统对当前正在运行的系统配置进行跟踪。当android系统检测到当前配置改变(如手机接入电脑),正在运行的应用的一些回调方法将会被调用,来处理如何响应这些配置的改变。关于回调我们稍后再讲解,现在我们先讨论一些相关资源。
android的一个特点就是会自动根据当前配置的改变来选择相应的资源文件,你不需要写代码来控制,你只需通过资源文件名来连接资源文件,android会为你选择适当的资源文件。比如,如果你的设备处于横屏模式,就调用landscape layout。代码只需要文件名,而不用对文件做出特别的指定。所有开发者所要考虑的应该是当配置会做出何种改变时,需要怎样的资源文件来创建。
为了使系统简单化,当配置改变时android会销毁当前的activity而创建一个新的activity,这看上去似乎很糟糕,但其实不是。以前开发的做法就是要考虑activity中哪些代码部分需要保留运行,哪些不需要保留,这对开发来说非常麻烦。一个activity被销毁时,会第一时间通知你那些信息需要存储。当新的activity创建时,你可以重新取出上一个activity的状态信息。如果为了更好的用户体验,很显示我们都不希望这些状态信息保持得太久。
值得注意的是,应用进程并没有被销毁,所有的东西都还在应用的context中,而不是当前activity的某个部分。当背景线程被剥离,或者数据库、provider仍然可用,这都是单例模式的功劳。运用这一优势,我们可以快速的对配置的改变做出相应。
二、activity状态
对于配置的改变,有三个回调函数:
onSaveInstanceState()
onCreate()
onRestoreInstanceState()
当配置改变,最先调用的是onSaveInstanceState(),你可以在配置改变结束时,保存一些activity的状态信息。它的调用在onStop()方法之前。对于这个回调方法,相信大家应该很熟悉了,我们大部分都在这个方法里做一些初始化当操作,比如设置布局,分配控件id等。如果你复写该方法,参数bundle 对象里可以存放一些配置信息。如果你使用super.onSaveInstanceState()来调用父类的方法,它就会帮你把bundle对象传进来。
想保持一些信息到bundle对象中,你可以使用putInt() putString()等方法。大家可以参考android.os.Bundle class。比如,使用putParcelable()可以保存一些复杂的对象。比如下面的例子:
@Override public void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putInt("counter", 1);
}
如果确保你的状态信息还存在,你可以恢复状态信息,使用onRestoreInstanceState()方法取出,如下所示:
@Override public void onRestoreInstanceState(Bundle icicle) {
super.onRestoreInstanceState(icicle);
int someInt = icicle.getInt("counter", -1);
}
你还可以用onCreate()来onSaveInstanceState()同样的事情
四、fragments状态
fragments的状态周期和activity非常类似,也是有一个onSaveInstanceState(),此外,还有onInflate(),onCreate(),onCreateView(),onActivityCreated().这就让我可选择多种方式从上一个状态重建framgment。
五、使用FragmentManager来存储Fragment状态。
还有另一种方式来保持状态,FragmentManager类有一个saveFragmentInstanceState()方法能用来调用产生一个Fragment.SavedState对象。使
用Fragment.SavedState对象去重建一个fragment可以通过setInitialSavedState()方法。