Android开发文档上专门有一小节解释这个问题。简单来说,Activity是负责与用户交互的最主要机制,任何“设置”(Configuration)的改变都可能对Activity的界面造成影响,这时系统会销毁并重建Activity以便反映新的Configuration。

“屏幕方向”(orientation)是一个Configuration,通过查看Configuration类的javadoc可以看到其他Configuration还有哪些:如fontScale、keyboardHidden和locale等等。

当屏幕旋转时,这个Configuration就发生了改变,因此当前显示的Activity需要被重建,Activity对象会被终止,它的onPause()、onStop()和onDestroy()方法依次触发,然后一个新的Activity对象被创建,onCreate()方法被触发。假设屏幕旋转前,用户正在手机上填写一个注册表单,如果处理不当,用户会发现旋转后的表单变成空白的了,严重影响使用体验。

要解决这个问题有三种方法:

方法1:禁止旋转屏幕

毫无疑问,这是最懒的办法了,相当于回避了本文提出的问题,方法如下看看就好:

<activity android:name=".MyActivity"
android:screenOrientation="portrait"
android:label="@string/app_name">

方法2:旋转后恢复现场

既然Activity会被销毁,那么我们就可以使用前文介绍过的“持久化/恢复现场”方法来解决。即在onPause()里将用户当前已经输入的内容保存到数据库或Preference,在onCreate()方法里读取并填充到表单中,这也是官方推荐的方法。

需要补充一点,如果Activity重建需要耗费大量资源或需要访问网络导致时间很长,可以实现onRetainNonConfigurationInstance()方法将所需数据先保存到一个对象里,像下面这样:

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

重建时,在onCreate()方法里通过getLastNonConfigurationInstance()方法获得之前保存的数据,如下所示:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data == null) {//表示不是由于Configuration改变触发的onCreate()
data = loadMyData();
}
...
}

方法3:手工处理旋转

一般情况下Configuration的改变会导致Activity被销毁重建,但也有办法让指定的Configuration改变时不重建Activity,方法是在AndroidManifest.xml里通过android:configChanges属性指定需要忽略的Configuration名字,例如下面这样:

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

这样设置以后,当屏幕旋转时Activity对象不会被销毁——作为替代,Activity的onConfigurationChanged()方法被触发,在这里开发者可以获取到当前的屏幕方向以便做必要的更新。既然这种情况下的Activity不会被销毁,旋转后Activity里正显示的信息(例如文本框中的文字)也就不会丢失了。

假如你的应用里,横屏和竖屏使用同一个layout资源文件,onConfigurationChanged()里甚至可以什么都不做。但如果横屏与竖屏使用不同的layout资源文件,例如横屏用res/layout-land/main.xml,竖屏用res/layout-port/main.xml,则必须在onConfigurationChanged()里重新调用setContentView()方法以便新的layout能够生效,这时虽然Activity对象没有销毁,但界面上的各种控件都被销毁重建了,你需要写额外的代码来恢复界面信息。

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig); // Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "横屏模式", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "竖屏模式", Toast.LENGTH_SHORT).show();
}
}

官方的Android开发文档不建议使用这种方式处理Configuration改变:

Note: Using this attribute should be avoided and used only as a last-resort. Please read Handling
Runtime Changes
 for more information about how to properly handle a restart due to a configuration change.

最佳实践

考虑到旋转屏幕并不是使Activity被销毁重建的唯一因素,仍然推荐前文介绍过的方法:在onPause()里持久化Activity状态,在onCreate()里恢复现场,可以做到一举多得;虽然Google不推荐设置android:configChanges属性的方式,但如果你的Activity横向纵向共用同一个layout文件,方法3无疑是最省事的。

参考资料:

Configuration
Changes
 

Handling
Runtime Changes


Activity
restart on rotation Android


How
to handle screen orientation change when progress dialog and background thread active?

本文地址:http://www.cnblogs.com/bjzhanghao/archive/2012/11/09/2761897.html

旋转屏幕导致Activity重建问题的解决办法的更多相关文章

  1. Android——旋转屏幕导致Activity重建解决方法

    Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何“设置”(Configuration)的改变都可能对Activity的界面造成影响,这时系 ...

  2. Android开发 旋转屏幕导致Activity重建解决方法(转)

     文章来源:http://www.jb51.net/article/31833.htm Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何“ ...

  3. 旋转屏幕导致Activity重建

    简单来说,Activity是负责与用户交互的最主要机制,任何“设置”(Configuration)的改变都可能对Activity的界面造成影响,这时系统会销毁并重建Activity以便反映新的Conf ...

  4. Android使用Unity导致Activity被销毁的解决办法

    由于需要在Android中使用Unity(Android的Activity会继承Unity提供的UnityPlayerActivity),可能是第三方的原因退出Unity后就导致Android整个应用 ...

  5. 记一次由于Java泛型类型擦除而导致的问题,及解决办法

    中所周知,Java中的泛型并不像C++.C#一样是真正的泛型,其泛型是通过类型擦除来实现的.具体什么是类型擦除,可以参看这篇博文:http://icyfenix.iteye.com/blog/1021 ...

  6. 关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法

    关于FusionCharts图表宽度width的设置问题导致图表显示异常的解决办法 题设: 经常使用FusionCharts图表的朋友可能会遇到这个问题.就是在FusionCharts显示的时候有时候 ...

  7. Linux  改动inittab文件及忘记密码等导致无法进入系统的解决办法

    改动inittab文件及忘记密码等导致无法进入系统的解决办法[摘] by:授客 QQ:1033553122 inittab是linux的系统启动模式配置文件,在”/etc“文件目录下没,其内容是: # ...

  8. MyEclipse格式化JSP代码导致Java表达式<%= %>自动换行的解决办法

    MyEclipse格式化JSP代码导致Java表达式<%= %>自动换行的解决办法: 可以将Java表达式<%= %>换成EL表达式.

  9. 20190603 - CentOS 7 提示 Failed to load SELinux policy. Freezing 导致卡住不启动的解决办法

    现象 最近 Windows 和两台 Mac 混用,将 Windows VirtualBox 中安装的 CentOS 7 拷贝到 Mac 上. 启动 CentOS 7 时,图形界面进度卡在最后,按 Es ...

随机推荐

  1. php str_repeat()函数 语法

    php str_repeat()函数 语法 str_repeat()函数怎么用? php str_repeat()函数用于重复使用指定字符串,语法是str_repeat(string,repeat), ...

  2. Digit

    Digit Accepted : 85   Submit : 308 Time Limit : 1000 MS   Memory Limit : 65536 KB  题目描述 我们把十进制整数依次写成 ...

  3. t时间同步服务设置

    中国国家授时中心的时间服务器IP地址及时间同步方法 大家都知道计算机电脑的时间是由一块电池供电保持的,而且准确度比较差经常出现走时不准的时候.通过互联网络上发布的一些公用网络时间服务器NTPserve ...

  4. Win7隐藏登录界面中的用户(不建议HOME版使用)

    一天一點 能登多高,靠的不是双脚!能看多远,靠的不是双眼!人生路,贵在坚持! Win7隐藏登录界面中的用户(不建议HOME版使用) Win7中如何隐藏不想出现在登录界面中的用户 在Windows系统管 ...

  5. html中map标签和area标签的应用(总结)

    html中map标签和area标签的应用(总结) 一.总结 一句话总结: html中map标签和area标签和组成图片地图,在前端优化中可以减少http请求 1.map标签的用途是什么? 图片地图:是 ...

  6. nginx相关总结

    1. Nginx 无法启动解决方法 在查看到 logs 中报了如下错误时: 0.0.0.0:80 failed (10013: An attempt was made to access a sock ...

  7. maven(一),maven3.5.3的windows安装及Eclipse集成

    maven用了好长时间,需要系统的学习一下.maven ,是一个项目构建的工具,是一个项目管理和综合工具,具有项目生命周期管理功能. maven现在到了3.5.3,就以这个版本进行. 一.下载mave ...

  8. Intellij IDEA 智能补全的 10 个姿势,简直不能太牛逼!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 一年多前,栈长那时候刚从 Eclipse 转型 IDEA 成功,前面转了好多次,都是失败史,都是泪.. 后面我就在微信公众号 ...

  9. C++中的抽象类和接口

    1,在 C++ 语言中,并不直接支持面向对象中的抽象类和接口概念,但是 C++ 语言 却可以间接实现这些概念: 2,什么是抽象类: 1,面向对象中的抽象(其实就是分类)概念: 1,在进行面向对象分析时 ...

  10. ubuntu 配置php环境

    第一步:先更新 sudo apt-get update 第二步:安装 安装 Apache2: sudo apt-get install apache2 安装PHP模块: sudo apt-get in ...