Android API Guides---Handing Runtime Changes

来源:互联网 发布:蓝牙音箱品牌知乎 编辑:程序博客网 时间:2024/05/16 02:06
处理运行时更改
有些设备配置可以在运行时改变(如屏幕方向,键盘可用性,和语言)。当这种变化发生时,Android的重新启动运行活动(的onDestroy()被调用,随后的onCreate())。重新启动行为旨在帮助您的应用程序自动重新加载相匹配新的设备配置,替代资源应用程序适应新的配置。


要正确处理重新启动,但重要的是你的活动通过正常的活动周期,其中的Andr​​oid的onSaveInstanceState调用(恢复以前的状态),它会破坏你的活动之前,这样就可以节省约应用程序状态的数据。然后,您可以的onCreate()或onRestoreInstanceState中恢复状态()。


要测试您的应用程序重新启动自身与应用程序的状态完好,应该调用配置更改(如更改屏幕方向),而在应用程序中执行各种任务。您的应用程序应该能够在任何时间,以处理事件,如配置更改,或者当用户的应用程序后,收到来电的电话,然后返回到你的应用程序更晚可能已经重新启动,而无需用户数据或状态的丢失销毁。要了解如何恢复活动状态,阅读有关的活动周期。


然而,你可能会遇到在重新启动应用程序并恢复显著的数据可能是昂贵的情况下,并创建一个不好的用户体验。在这种情况下,你还有其他两个选项:


配置变化时保持一个对象
允许在配置改变你的活动重新启动,但携带状态的对象将活动的新实例。
处理配置改变自己
从在某些配置更改重新启动活动防范系统,但收到一个回调时做配置变化,这样您就可以手动更新您的活动是必要的。
留住一个对象在配置变化


如果重新启动活动要求你恢复大型数据集,重新建立网络连接,或执行其他密集型操作,然后一个完整的重新启动由于配置改变可能是一个缓慢的用户体验。此外,它可能无法为你完全恢复同捆的活动状态,该系统节省了您的的onSaveInstanceState()回调,它不是设计来进行内就必须大对象(如位图)和数据然后被序列化反序列化,这会消耗大量的内存和进行配置更改缓慢。在这种情况下,你可以缓解经重新初始化保留了片段重新启动你的活动时,你的活动的负担,由于配置改变。这个片段可以包含你希望保留状态的对象引用。


当Android系统的活动关闭由于配置改变,你的活动,你已标记保留片段不被破坏。你可以这样的片段添加到您的活动,以保持状态的对象。


要运行时配置更改期间保留片段状态的对象:


扩展片段类,并宣布到你的状态的对象引用。
呼叫setRetainInstance(布尔)时创建的片段。
片段添加到您的活动。
使用FragmentManager重新启动活动时检索片段。

例如,定义您的片段如下:

public class RetainedFragment extends Fragment {    // data object we want to retain    private MyDataObject data;    // this method is only called once for this fragment    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // retain this fragment        setRetainInstance(true);    }    public void setData(MyDataObject data) {        this.data = data;    }    public MyDataObject getData() {        return data;    }}
注意:虽然您可以存储任何对象,你不应该传递是联系在一起的活动,如可绘制,适配器,视图或与上下文关联的其他对象的对象。如果你这样做,它会泄漏原来的活动实例的所有意见和资源。 (泄漏资源意味着应用程序保持对他们的保留,他们不能被垃圾收集的,所以大量的内存可能会丢失。)


然后使用FragmentManager该片段添加到活性。在活动期间运行时配置的变化再次启动,您可以从片段中的数据对象。例如,定义您的活动如下:

public class MyActivity extends Activity {    private RetainedFragment dataFragment;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        // find the retained fragment on activity restarts        FragmentManager fm = getFragmentManager();        dataFragment = (DataFragment) fm.findFragmentByTag(“data”);        // create the fragment and data the first time        if (dataFragment == null) {            // add the fragment            dataFragment = new DataFragment();            fm.beginTransaction().add(dataFragment, data”).commit();            // load the data from the web            dataFragment.setData(loadMyData());        }        // the data is available in dataFragment.getData()        ...    }    @Override    public void onDestroy() {        super.onDestroy();        // store the data in the fragment        dataFragment.setData(collectMyLoadedData());    }}
在这个例子中,的onCreate()增加了一个片段或恢复到它的参考。 OnCreate()中还存储片段实例中的状态的对象。的onDestroy()更新保留片段实例中的状态的对象。


处理配置改变自己


如果你的应用程序不需要特定的配置更改过程中更新的资源,你必须要求你避免活动启动性能的限制,那么你可以声明你的活动处理的配置变化本身,它阻止系统重新启动活动。


注:处理配置更改自己可以使它更难以利用替代资源,因为系统不会自动为您应用这些。这种技术应被视为最后的手段,当你必须避免由于配置更改重新启动,因此不建议对大多数应用程序。


要声明的活动处理的配置变化,在你的清单文件编辑适当<活动>元素包括了android:configChanges与代表要处理的配置属性的值。可能的值列对于Android的文档中:configChanges属性(最常用的值是“方向”,以防止重新启动时屏幕方向的变化和“keyboardHidden”,以防止重新启动时键盘的可用性的变化)。 |您可以通过用管分离申报属性的多个配置值字符。


例如,下面的清单代码声明,说明如何处理屏幕方向变化和键盘的可用性变化的活动

<activity android:name=".MyActivity"          android:configChanges="orientation|keyboardHidden"          android:label="@string/app_name">
现在,当这些配置的一个变化,MyActivity不会重新启动。而是,MyActivity接收呼叫到onConfigurationChanged()。这种方法是通过一个配置对象,指定新的设备配置。通过读取配置字段,可以判断新的配置,并通过更新在界面中使用的资源进行适当的更改。在这个方法被调用的时候,您的活动的资源对象更新返回基于新的配置资源,让您可以轻松重置您的UI元素没有系统重新启动的活动。
注意:与Android 3.2(API等级13)开始,“屏幕尺寸”也随之变化时,纵向和横向之间的设备切换。因此,如果你想防止因方向改变运行时重新启动了API级别13或更高的开发时(以作为的minSdkVersion声明并targetSdkVersion属性),则必须包含除“方向”值“屏幕尺寸”的价值。也就是说,你必须声明的android:configChanges =“方向|屏幕尺寸”。但是,如果你的应用程序面向API级别12或更低,那么你的活动总是处理此配置变化本身(在Android 3.2或更高版本的设备上运行时,此配置更改不会重新启动您的活动,甚至)。
例如,下面的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();    }}
配置对象表示当前所有的配置,而不​​仅仅是已经改变的人。大多数时候,你不会在乎究竟如何配​​置已发生变化,可以简单地重新分配所有资源提供替代品,你处理的配置。例如,由于资源对象现已更新,您可以重新使用setImageResource()和新配置相应的资源图像浏览时(如在提供资源中所述)。
请注意,从配置字段中的值是相匹配从配置类特定的常量整数。对于文档中关于该常数随每个字段使用,请参阅相应的字段中配置的参考。
记住:当你声明你的活动,以处理配置更改,你有责任为重置您提供替代的任何元素。如果声明你的活动来处理方向变化,具有应在横向和纵向之间切换图像,必须在每个资源onConfigurationChanged期间重新分配给每个元素()。
如果您不需要更新基于这些配置更改您的应用程序,你就不再需要实施onConfigurationChanged()。在这种情况下,所有的配置更改之前使用的资源仍然在使用,你才避免了您的活动的重新启动。然而,你的应用程序应该总是能够关闭和其以前的状态完好重新启动,所以你不应该考虑这种技术从正常活动的生命周期中保持你的状态逃跑。这不仅是因为有其他的配置更改,您无法重新启动您的应用程序阻止,而且还因为您需要处理事件当用户离开你的应用程序,例如,它被用户返回到之前销毁。
欲了解更多有关该配置更改您可以在活动的处理,看到了android:configChanges文件和配置类。

0 0
原创粉丝点击