Android 资源之处理运行时更改(Handling Runtime Changes)

1、概述

   Android之Handling Runtime Changes(处理运行时更改)一些设备配置在运行过程中可能会发生改变(例如屏幕横向布局、键盘可用性和语言)。当这样的变化发生时,Android会重新启动这个正在运行的Activity(onDestroy()方法会被调用,然后调用onCreate()方法)。这个重启的动作是为了通过自动往你的应用程序中载入可替代资源,从而使你的应用适应新的配置。为了正确执行一次重启,你的Activity在整个生命周期中重新保存它之前的状态是很重要的,Android是通过在销毁你的Activity之前调用onSaveInstanceState()方法来保存关于应用之前状态的数据。然后你就可以在onCreate()方法或者onRestoreInstanceState()方法中重新保存应用的状态了。为了测试你的应用可以通过应用的状态原封不动地重启自己,你应该给你的应用授权当程序在执行不同的任务时应用的配置可以改变(例如屏幕的方向变化)。为了处理一些事件,例如当用户接听一个打入的电话然后返回到你的应用程序中,在没有丢失用户数据或者状态信息的情况下,你的应用应该具备在任何时候重启自己的能力(更多参见Activity lifecycle)。
然而,你可能要面对这样一个情景,重启你的应用程序并重新保存大量有价值的数据会导致很差的用户体验。在这样的情景面前,你有两种如下两种选择。

2、在配置改变期间维持一个对象  

    当你的Activity由于配置发生改变要关闭的时候,Android会在执行onStop()方法与onDestroy()方法之间调用onRetainNonConfigurationInstance()方法。为了在配置改变后更有效地保存状态,在实现onRetainNonConfigurationInstance() 方法时你应该返回你所需要的一个对象。当你的应用程序需要从网上下载很多数据的时候。如果用户更改设备的方向并且Activity重启,你的应用程序必须要重新载入数据,那就会很慢了。你需要做的就是实现onRetainNonConfigurationInstance() 方法并返回带有你的数据的对象,然后当你的 Activity通过getLastNonConfigurationInstance()方法重启时就能获取数据。

   a. 重写 onRetainNonConfigurationInstance() 方法来返回你想要维护的对象

@Override
public Object onRetainNonConfigurationInstance() {
    final MyDataObject data = collectMyLoadedData();
    return data; 
}

    特别提醒:当你要返回任何对象的时候,你应该不要传递一个跟Activity有关联的对象,例如一个Drawable对象,一个Adapter对象,一个View对象或者任何其他跟Context相关的对象。如果你这样做,它会泄漏原来Activity实例的所有视图和资源。(泄漏资源意味着您的应用程序保持对他们的持有,他们不能被当做垃圾收集,因此内存就丢失了)。

   b. 当你的Activity再次创建时,调用getLastNonConfigurationInstance()方法恢复你的对象

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
   final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
   if (data == null) {
     data = loadMyData();
   }
    ...
}

3、自己来处理配置的变化

    如果在某个特殊的配置发生改变的期间你的应用程序不需要更新资源,而且你有个操作限制需要你避免Activity的重启,那么你可以声明使你自己的Activity来处理配置的变化,从而阻止系统重启你的Activity。特别提醒: 选择自己来处理配置的变化会使得可替代资源的使用变得更困难,因为系统不会为你来自动调用这些资源。这种技术应该被视为最后的手段,对于大多数应用程序不建议使用。
    为了声明你的Activity来处理配置的变化,在清单文件中编辑正确的<activity>元素,包括赋好值的android:configChanges属性,代表你要处理的配置。android:configChanges属性所有可能的值都要在文档中列出(最常用的值是:orientation来处理当屏幕的方向变化时,keyboardHidden来处理键盘可用性改变时)。你可以在属性中声明多个配置的值,通过“|”符号将它们分隔开。例如,以下清单片段声明了Activity中将同时处理屏幕的方向变化和键盘的可用性变化:

<activity android:name=".MyActivity"
    android:configChanges="orientation|keyboardHidden"
    android:label="@string/app_name">

        当这些配置中的一个发生改变时,MyActivity不会重新启动。相反,这个 Activity会接收onConfigurationChanged()方法的调用。这个方法传递一个Configuration类的对象来标识新的设备配置。通过读取配置字段,你可以确定新的配置信息并通过更新你界面中使用的资源来正确应用这些改变。任何时候这个方法被调用,你的Activity的Resources对象会被更新并返回一个基于新配置的Resources对象,因此你可以在不用系统重启你的Activity的情况下很容易地重置你的UI元素。

   在Android 3.2开始,屏幕方向screeSize也变化:android:configChanges="orientation|screenSize" 

@Override
public 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();
    }
}
    这个Configuration类的对象代表着当前所有的配置信息,不仅仅那些改变的配置信息。在很多时候,你不会确切地在乎这些配置是怎么改变的,并且可以简单地重新分配所有资源,提供您正在处理的配置的可替代资源。例如,因为这个Resources对象现在被更新,你可以通过setImageResource(int)方法重置任何ImageView,并重置恰当的资源给当前配置使用(详见:Providing Resources)。请注意,配置字段的值是一些匹配Configuration类里特定的常量的整数。对于文档中的每个字段使用那个常量,请在Configuration类中参阅相应的字段。记住:当你声明你的Activity来处理配置的变化时,你负责重置所有你提供可替代资源的元素 。如果你声明你的Activity来处理屏幕方向的改变并具有在横向和纵向之间切换的图像,你必须在onConfigurationChanged()方法中给每个元素重新指定一个资源。如果你不需要根据配置的变化来更新你的程序,你可以不实现onConfigurationChanged()方法。在这种情况下,所有在配置改变之前使用的资源仍然会被使用,并且你只需要避免你的Activity被重启。然而,您的应用程序应该始终能够关闭并从其之前的状态完好地重新启动。这不仅是因为存在有一些配置发生改变时你不能防止它重新启动您的应用程序,而且为了处理一些事件,例如当用户接收了电话然后返回到应用程序。更多关于哪些配置变化时你可以在你的Activity中处理,参见android:configChanges文档和Configuration类。

参考:http://developer.android.com/guide/topics/resources/runtime-changes.html

           http://wiki.eoeandroid.com/Handling_Runtime_Changes



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值