系统的一些设置可能在运行时发生改变(比如屏幕方向,键盘显示/隐藏,语言设置等)。当这种改变发生时,Android会重启当前Activity(先后调用onDestroy()和onCreate()方法)。重启Activity是为了使应用程序能够适应新的设置,并自动加载与新设置相关的资源。 为了防止程序运行状态的丢失,在Activity重启过程中需要进行适当的处理。在Activity的生命周期中,系统会在Activity消失前调用onSaveInstanceState()方法,在该方法中我们可以保存程序当前的状态,然后在重启后的onCreate()或者onRestoreInstanceState()方法中恢复到之前保存的状态。 但是有时候重新启动Activity时要恢复大量的数据,这会花费较大的代价,缺乏良好的用户体验。有两种方法可以解决这个问题: (1)设置改变时保存一个对象 (2)允许Activity在设置改变时重新启动,但是会传递一个Object对象给新的Activity实例
1. 保存对象
如果重启Activity需要恢复大量数据,重新建立网络连接,或者进行其他耗费资源的操作,在设置改变时完全重启Activity对用户来说可能太慢了。系统通过调用onSaveInstanceState()方法自动保存的Bundle对象可能不足以完全恢复Activity的运行状态——这种方法不是为了传递大的对象(比如位图)而设计的,并且这种方法传递的对象要进行序列化和逆序列化操作,耗费大量的内存,导致延长设置变更过程花费的时间。在这种情况下,我们可以通过一个Object对象保存与Activity运行状态相关的数据,减轻Activity的重启的负担。
在设置改变时保存一个对象: 重写onRetainNonConfigurationInstance()方法,返回我们想要保存的对象 当Activity重新被创建时,调用getLastNonConfigurationInstance()恢复对象 当Android系统因设置改变停止Activity时,它会在onStop()和onDestroy()两个回调函数之间调用onRetainNonConfigurationInstance()。在onRetainNonConfigurationInstance()方法中,我们可以返回任何Object对象,从而在设置改变后快速恢复Activity的状态。
一个有价值的利用场景是:我们的应用程序在启动时从网络加载大量数据。如果用户改变了屏幕的方向导致Activity重启,重新从网络获取数据是比较慢的。我们可以实现onRetainNonConfigurationInstance()方法并返回一个对象,这个对象中包含了Activity已从网络加载的数据,并通过getLastNonConfigurationInstance()重新获取。例如:
@Overridepublic Object onRetainNonConfigurationInstance() {    final MyDataObject data = collectMyLoadedData();    return data;}

需要注意的是,虽然可以返回任何对象,但是我们应该避免返回那些与Activity绑定的对象,比如Drawable,Adapter,View,或者其他任何与Context相关联的对象。如何这样做了,会导致原Activity实例的所有视图和资源的泄露(无法被垃圾回收机制回收,占用内存资源)。
Activity再次启动时获取保存的数据:
@Overridepublic void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.main);     final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();    if (data == null) {        data = loadMyData();    }    ...}


getLastNonConfigurationInstance()的返回值就是onRetainNonConfigurationInstance()的返回值。如果data为空(Activity不是因为设置的改变而启动时,会发生这种情况)这段代码会使用正常的流程初始化data对象。
2. 手动响应设置改变
如果应用程序在某些设置改变时不需要更新资源,并且出于性能原因要避免Actvity的重启,我们可以声明由Activity自己来处理设置的变更。一般来说,不推荐使用这种方法,除非一定要避免因设置改变导致的Activity重启。 通过为AndroidManifest.xml文件中的元素增加android:configChanges属性来设置此Activity手动响应设置的改变,该属性的值是我们需要手动处理的相关设置。最常用的值是orientation(在屏幕方向改变时阻止Activity重启)和keyboardHidden(在键盘显示/消失时阻止Activity重启)。多个设置值可以同时进行声明,使用“|”进行分隔。 例如,下面的manifest代码声明一个Activity手动响应屏幕方向改变和键盘状态的改变:
<activity android:name=".MyActivity"          android:configChanges="orientation|keyboardHidden"          android:label="@string/app_name">

此时,当声明中的某一个设置改变时,MyActivity不会重启,而是去调用onConfigurationChanged()回调方法。这个方法传递一个Configuration对象,指明了新的设置。通过读取Configuration,我们可以获得新的设置信息并据此进行一些适当的操作。
下面的代码示例中,onConfigurationChanged()检查了设备当前的屏幕方向设置:
@Overridepublic void 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();    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();    }}



更多相关文章

  1. Android(安卓)ContentProvider UnderStanding
  2. 在Android中使用Lombok减少编码
  3. Android支持多并发的异步任务框架MultiAsynctask
  4. MTP 服务流程
  5. android中数字及模拟小时钟设计
  6. Android数据持久化之File机制分析
  7. Eclipse启动失败Android(安卓)sdk content loader 0%的四种解决
  8. Android(安卓)studio build.gradle 各种错误解决总结
  9. Android关于触摸事件跟点击事件两个方法的关系

随机推荐

  1. MySql导入CSV文件或制表符分割的文件
  2. Navicat把csv数据导入mysql
  3. Navicat for SQLite导入csv中文数据的方
  4. Navicat for MySql可视化导入CSV文件
  5. 使用navicat将csv文件导入mysql
  6. MySQL数据表合并去重的简单实现方法
  7. mysql 循环批量插入的实例代码详解
  8. 详解MYSQL中重命名procedure的一种方法
  9. Oracle开启和关闭的四种模式
  10. MySQL并发更新数据时的处理方法