android 设备在程序的运行过程中,设备的配置信息可能动态更新,如屏幕方向,设备本地语言。当这些参数一旦更改时,那么你的应用程序将重新启动(从ondestory----onCreate),在重启的过程中系统将会去加载程序提供的其他资源配置,以达到适应最新设备配置,让应用程序运行更好。
要想程序在重启后能显示之前的信息,那么在activity的生命周期中保存重启之前的状态是非常重要的{调用 onSaveInstanceState()}
,在程序重启后,可以在onCreate()或者在onRestoryInstanceState()方法
恢复重启之前的状态。
然而在某些情况,因配置改变而重新启动程序并且保存程序状态信息需要付出很大的代价,而且有可能产生非常不好的用户体验,那么此时你有两种选择:
使用状态变量保存状态更改信息 允许程序在配置更改时重新启动,将程序的信息保存在状态变量中,并将新的状态变量传递到新的 activity 重启activity意味着你需要恢复大量的数据,重新建立网络连接或者其他的一些操作。要全面恢复 以前的状态信息有可能会导致用户体验的降低,当然你也不可能完全的恢复activity状态通过android的 onSaveInstanceState()方法将activity的状态信息保存在一个类型map的bundle中,因为bundle的设计 初衷并不能携带大量数据(如bitmap),它所能携带的数据是可以序列化和反序列化的。在activity重启时 可以通过保留activity重启前的状态信息来减少重启时activity的压力。 1、重写onRetainNonConfigurationInstance()方法来保存你想保留的activity信息。 2、当你的activity重启时,你可以通过
调用getLastNonConfigurationInstance()方法恢复之 前的状态。 当android系统因设备配置改变要销毁你的activity时,系统会在onStop()和onDestory()之间调用
onRetainNonConfigurationInstance()方法,在该方法中你可以返回任意对象来保存你的activity 状态。 假设有这样一个场景,当你的应用程序通过网络下载数据,在下载完成后设备的屏幕方向改变了,那 么你的activity将重新启动,再次不得不去重新下载数据,那么用户体验非常糟糕。此时你可以在
onRetainNonConfigurationInstance()方法中返回你已经加载的数据,在activity重新启动后在恢 复已加载的数据。
@OverridepublicObject onRetainNonConfigurationInstance(){ final MyDataObject data = collectMyLoadedData(); return data; } @Overridepublicvoid onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); finalMyDataObject data =(MyDataObject) getLastNonConfigurationInstance(); if(data ==null){ data = loadMyData(); } ...} 注:当然在返回任何对象后,你不能给该activity绑定任何对象,这样会导致绑定的对象同activity生命 绑定,不能被垃圾回收机制回收,从而浪费大量的内存。
自己处理状态信息 不允许程序在配置更改时重新启动,你可以接受到一个回调当设备配置信息改变时,然后手动更新的 activity 如果你的应用程序不需要更新页面信息并且不想activity重新启动,那么需要定义activity去处理设 备配置更改以预防activity重新启动。 手动预防哪一类配置改变你需要修改manifest.xml文件中activity 节点的配置,添加android: configChanges
属性,添加你要防止的设备更改值(参考)即可,你也可以添加多个属性值,它们之间 使用"|"隔开。 <activityandroid:name=".MyActivity" android:configChanges="orientation|keyboardHidden" //屏幕方向改变和键盘隐藏 android:label="@string/app_name"> 如添加以上配置是,当屏幕方向改变或者键盘隐藏时,activity都不会重新启动,activity会调用onConfig urationChange()方法,该方法中会传递一个新的configuration,同过读取configuration可以动态更新 你的UI显示,而不是重新启动Activity。 @Override publicvoid onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); // Checks the orientation of the screen if(newConfig.orientation ==Configuration.ORIENTATION_LANDSCAPE){ Toast.makeText(this,"landscape",Toast.LENGTH_SHORT).show(); }elseif(newConfig.orientation ==Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this,"portrait",Toast.LENGTH_SHORT).show(); } 注:在android3.2中方向改变需要添加screen size,3.2以下的版本不需要添加该属性android:configChanges="orientation|screenSize"