文档章节

旋转屏幕导致Activity重建

jdroid
 jdroid
发布于 2014/04/20 13:16
字数 1068
阅读 1707
收藏 32

当屏幕旋转时,这个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()方法将所需数据先保存到一个对象里,像下面这样:

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

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

@Overridepublic 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|keyboardHidden"
          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对象没有销毁,但界面上的各种控件都被销毁重建了,你需要写额外的代码来恢复界面信息。

@Overridepublic 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


© 著作权归作者所有

共有 人打赏支持
jdroid
粉丝 16
博文 84
码字总数 23247
作品 0
海淀
加载中

评论(3)

我叫什么
我叫什么

引用来自“EREHMii”的评论

方法2: onRetainNonConfigurationInstance 相比 onSaveInstanceState 是更便利点, 唯一不好看的就是onRetainNonConfigurationInstance 被官方打上了废弃标签

方法3: 禁用旋转时重建Activity的声明应该是这样的: <activity android:name=".MainActivity" android:configChanges="orientation|keyboardHidden|screenSize"/>

screenSize 这个是较新版本要求的.
楼上说的很对 问题已经能解决了
有初啊
有初啊
方法2: onRetainNonConfigurationInstance 相比 onSaveInstanceState 是更便利点, 唯一不好看的就是onRetainNonConfigurationInstance 被官方打上了废弃标签

方法3: 禁用旋转时重建Activity的声明应该是这样的: <activity android:name=".MainActivity" android:configChanges="orientation|keyboardHidden|screenSize"/>

screenSize 这个是较新版本要求的.
猪星阿呆
猪星阿呆
写的很好!
Android Activity或进程重启时数据保存与恢复

前言 onRestoreInstanceState用来在意外中断时恢复保存的数据,onSaveInstanceState在意外中断时保存数据。这2个方法的使用是有条件的,因此,我们需要明白这2个方法触发的条件。 一、onSav...

IamOkay
2014/10/26
0
0
Android中Dialog与DialogFragment的对比

最近学习对话框时发现有两种类型的可供使用,一种是Dialog,另一种则是Android 3.0 引入的基于Fragment的DialogFragment。 从代码的编写角度看,Dialog使用起来要更为简单,但是Google则是推...

风荷举
2013/11/26
0
1
使用 PopupWindow 的注意事项

预备知识 使用 PopupWindow 之前, 一定要知道 Android 是怎么响应旋转屏幕的. 如果不知道的话, 那就先去了解下这个知识点. >>> Google 关键词: Android Activity 重建 另外需要知道的就是Pop...

有初啊
2013/11/07
0
2
使用Kotlin构建MVVM应用程序—提高篇:ViewModel

写在前面 大家好,这里是使用Kotlin构建MVVM应用程序—提高篇:ViewModel。 本篇文章将介绍google推荐的架构组件ViewModel的使用方法及实现原理。 为什么要有ViewModel? 为什么?看到ViewMod...

ditclear
07/04
0
0
Android 第六课——Activity生命周期

声明:本文转载自 http://blog.csdn.net/liuhe688/article/details/6733407 , 感觉读了这篇文章之后,对Activity又是一个更深层次的理解,所以果断手贱转载了!希望自己以后能多看看这篇文章...

learn_more
2015/01/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

学习设计模式——命令模式

参考博客 1. 认识命令模式 1. 定义:将一个请求封装成为一个对象,从而可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,并支持可撤销操作。 2. 组织结构: Commond:定义命令的...

江左煤郎
16分钟前
0
0
字典树收集(非线程安全,后续做线程安全改进)

将500W个单词放进一个数据结构进行存储,然后进行快速比对,判断一个单词是不是这个500W单词之中的;来了一个单词前缀,给出500w个单词中有多少个单词是该前缀. 1、这个需求首先需要设计好数据结...

算法之名
昨天
6
0
GRASP设计模式

此文参考了这篇博客,建议读者阅读原文。 面向对象(Object-Oriented,OO)是当下软件开发的主流方法。在OO分析与设计中,我们首先从问题领域中抽象出领域模型,在领域模型中以适当的粒度归纳...

克虏伯
昨天
0
0
Coding and Paper Letter(四十)

资源整理。 1 Coding: 1.Tomislav Hengl撰写的非官方作者指南:Michael Gould•Wouter Gerritsma。 UnofficialGuide4Authors 2.R语言包rwrfhydro,社区贡献的工具箱,用于管理,分析和可视化...

胖胖雕
昨天
0
0
JAVA 内存回收

参考:https://www.cnblogs.com/leesf456/p/5218594.html 1,JMV 中哪些可以作为 GC Root? 1. 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。 2. 方法区中的类静态属性引...

Carlyle_Lee
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部