Android开发者指南(21) —— Handling Runtime Changes

简介:

处理运行时更改

一些设备配置在运行过程中可能会发生改变(例如屏幕横向布局、键盘可用性和语言)。当这样的变化发生时,Android会重新启动这个正在运行的ActivityonDestroy()方法会被调用,然后调用onCreate()方法)。这个重启的动作是为了通过自动往你的应用程序中载入可替代资源,从而使你的应用适应新的配置。

为了正确执行一次重启,你的Activity在整个平凡的生命周期中重新保存它之前的状态是很重要的,Android是通过在销毁你的Activity之前调用onSaveInstanceState()方法来保存关于应用之前状态的数据。然后你就可以在onCreate()方法或者onRestoreInstanceState()方法中重新保存应用的状态了。为了测试你的应用可以通过应用的状态原封不动地重启自己,你应该给你的应用授权——当程序在执行不同的任务时应用的配置可以改变(例如屏幕的方向变化)。

为了处理一些事件,例如当用户接听一个打入的电话然后返回到你的应用程序中,在没有丢失用户数据或者状态信息的情况下,你的应用应该具备在任何时候重启自己的能力(更多参见Activity lifecycle)。

然而,你可能要面对这样一个情景,重启你的应用程序并重新保存大量有价值的数据会导致很差的用户体验。在这样的情景面前,你有两种选择:

a.         在配置改变期间维持一个对象

当配置发生改变时允许你的Activity重启,但让其携带一个有状态的对象到你的新Activity实例中。

b.         你自己来处理配置的变化

当某些配置发生变化的时候阻止系统重启你的Activity,并且当配置改变时要接收一个回调,这样你就可以根据需要来手动更新你的Activity

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

    如果重启你的Activity,你需要恢复大量的数据,重新执行网络连接,或者其他深入的操作,这样由配置改变引起的一次完全启动就会引起不好的用户体验。而且,仅有Activity生命周期中为你保存的的Bundle对象,你是不可能完全维护你的Activity的状态的不能传递很大的对象(如bitmap对象),并且这些对象里面的数据必须序列化,然后解序列化,这些都需要消耗很多内存从而使配置改变得很慢。在这样的情境下,当你的Activity由于配置发生改变而重启时,你可以通过重新预置一个有状态的对象来减缓你程序的负担。

         在运行期间配置改变时维护一个对象:

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

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

当你的Activity由于配置发生改变要关闭的时候,Android会在执行onStop()方法与onDestroy()方法之间调用onRetainNonConfigurationInstance()方法。为了在配置改变后更有效地保存状态,在实现onRetainNonConfigurationInstance() 方法时你应该返回你所需要的一个对象。

这个场景的可贵之处在于当你的应用程序需要从网上下载很多数据的时候。如果用户更改设备的方向并且Activity重启,你的应用程序必须要重新载入数据,那就会很慢了。你需要做的就是实现onRetainNonConfigurationInstance() 方法并返回带有你的数据的对象,然后当你的 Activity通过getLastNonConfigurationInstance()方法重启时就能获取数据。例如:

@Override

public Object onRetainNonConfigurationInstance() {

    final MyDataObject data = collectMyLoadedData();

    return data;

}

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

然后当你的Activity重启时获取数据:

@Override

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

 

    final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();

    if (data == null) {

        data = loadMyData();

    }

    ...

}

这个例子中,getLastNonConfigurationInstance()获取了onRetainNonConfigurationInstance()方法中保存的数据。如果数据为空,(这种情况发生在,当Activity重启是由其他原因而不是配置改变引起的)那么程序将从原来的数据源载入数据对象 

你自己来处理配置的变化

    如果在某个特殊的配置发生改变的期间你的应用程序不需要更新资源,而且你有个操作限制需要你避免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类的对象来标识新的设备配置。通过读取配置字段,你可以确定新的配置信息并通过更新你界面中使用的资源来正确应用这些改变。任何时候这个方法被调用,你的ActivityResources对象会被更新并返回一个基于新配置的Resources对象,因此你可以在不用系统重启你的Activity的情况下很容易地重置你的UI元素。

         注意:Android 3.2 (API level 13)开始,"screen size"也随着设备的横竖屏切换而改变。因此,如果你在API level 13或更高(minSdkVersiontargetSdkVersion属性声明)进行开发时,要防止因方向改变而重新启动,你必须为" orientation "添加"screen size"值。也就是说,你必须定义android:configChanges="orientation|screenSize"。但是,如果你的应用程序目标API level12或更低,你的activity总是要处理配置更改(配置更改没有重新启动你的activty,即使运行在Android 3.2或更高版本的设备)。

         例如,接下来的onConfigurationChanged()方法中实现了检查硬件键盘的可用性和当前设备的方向:

@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类。

本文转自博客园农民伯伯的博客,原文链接:Android开发者指南(21) —— Handling Runtime Changes,如需转载请自行联系原博主。

目录
相关文章
|
1月前
|
Android开发 Swift iOS开发
iOS和安卓作为主流操作系统,开发者需了解两者差异以提高效率并确保优质用户体验。
【10月更文挑战第1天】随着移动互联网的发展,智能手机成为生活必需品,iOS和安卓作为主流操作系统,各有庞大的用户群。开发者需了解两者差异以提高效率并确保优质用户体验。iOS使用Swift或Objective-C开发,强调简洁直观的设计;安卓则采用Java或Kotlin,注重层次与动画。Swift和Kotlin均有现代编程特性。此外,iOS设备更易优化,而安卓需考虑更多兼容性问题。iOS应用仅能通过App Store发布,审核严格;安卓除Google Play外还可通过第三方市场发布,审核较宽松。开发者应根据需求选择合适平台,提供最佳应用体验。
62 3
|
3月前
|
Shell Linux 开发工具
"开发者的救星:揭秘如何用adb神器征服Android设备,开启高效调试之旅!"
【8月更文挑战第20天】Android Debug Bridge (adb) 是 Android 开发者必备工具,用于实现计算机与 Android 设备间通讯,执行调试及命令操作。adb 提供了丰富的命令行接口,覆盖从基础设备管理到复杂系统操作的需求。本文详细介绍 adb 的安装配置流程,并列举实用命令示例,包括设备连接管理、应用安装调试、文件系统访问等基础功能,以及端口转发、日志查看等高级技巧。此外,还提供了常见问题的故障排除指南,帮助开发者快速解决问题。掌握 adb 将极大提升 Android 开发效率,助力项目顺利推进。
94 0
|
1月前
|
IDE Android开发 iOS开发
探索安卓与iOS系统的技术差异:开发者的视角
本文深入分析了安卓(Android)与苹果iOS两大移动操作系统在技术架构、开发环境、用户体验和市场策略方面的主要差异。通过对比这两种系统的不同特点,旨在为移动应用开发者提供有价值的见解,帮助他们在不同平台上做出更明智的开发决策。
|
2月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
373 3
|
2月前
|
IDE Java Android开发
安卓与iOS开发环境的差异及其对开发者的影响
在数字时代的浪潮中,移动应用成为人们生活的延伸。两大操作系统——安卓与iOS,如同两座技术高峰,各自占据着半壁江山。本文将探索这两个平台的开发环境差异,并讨论这些差异如何塑造开发者的编程习惯与职业选择。我们将从工具和语言、用户界面设计、系统架构、市场定位以及开发社区和资源五个方面进行比较,旨在为开发者提供一份实用的指南,帮助他们在不断变化的技术世界中,找到适合自己的发展路径。
55 3
|
2月前
|
移动开发 开发工具 Android开发
安卓与iOS开发:平台差异及其对开发者的影响
在移动开发的大潮中,安卓和iOS两大阵营各领风骚。本文将探讨这两个平台的关键差异,包括开发环境、编程语言、用户界面设计、应用分发以及商业模式等方面。通过比较分析,我们旨在为开发者提供一个清晰的指导,帮助他们根据项目需求和个人偏好做出明智的平台选择。同时,文章也将分享一些跨平台开发工具的使用经验,以期最大化开发效率和市场覆盖。
70 1
|
3月前
|
开发工具 Android开发 iOS开发
安卓与iOS开发环境的差异及其对开发者的影响
【8月更文挑战第22天】在移动开发的广阔舞台上,安卓与iOS两大操作系统各自占据着半壁江山。它们不仅是用户手中的智能设备,更是开发者展示创意和技术的战场。本文将深入探讨这两个平台的开发环境差异,以及这些差异如何塑造开发者的技术路线和职业生涯。从编程语言到开发工具,从市场定位到用户需求,我们将一探究竟,这两种不同的生态系统是如何影响开发者的决策和成长的。
|
3月前
|
Java 开发工具 Android开发
安卓与iOS开发环境的差异及其对开发者的影响
【8月更文挑战第21天】在移动应用开发的广阔天地中,安卓和iOS两大平台各据一方,它们不仅在用户体验上有所区别,更在开发环境上展现出独特的风貌。本文将深入探讨这两大平台的开发环境差异,以及这些差异如何塑造开发者的技术路径和职业生涯。从工具和语言的选择到市场份额的争夺,我们将一一剖析,以期为即将踏入这一领域的新手开发者提供一盏明灯。
|
2月前
|
监控 算法 数据可视化
深入解析Android应用开发中的高效内存管理策略在移动应用开发领域,Android平台因其开放性和灵活性备受开发者青睐。然而,随之而来的是内存管理的复杂性,这对开发者提出了更高的要求。高效的内存管理不仅能够提升应用的性能,还能有效避免因内存泄漏导致的应用崩溃。本文将探讨Android应用开发中的内存管理问题,并提供一系列实用的优化策略,帮助开发者打造更稳定、更高效的应用。
在Android开发中,内存管理是一个绕不开的话题。良好的内存管理机制不仅可以提高应用的运行效率,还能有效预防内存泄漏和过度消耗,从而延长电池寿命并提升用户体验。本文从Android内存管理的基本原理出发,详细讨论了几种常见的内存管理技巧,包括内存泄漏的检测与修复、内存分配与回收的优化方法,以及如何通过合理的编程习惯减少内存开销。通过对这些内容的阐述,旨在为Android开发者提供一套系统化的内存优化指南,助力开发出更加流畅稳定的应用。
73 0
|
3月前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
96 1
下一篇
无影云桌面