当前位置: 移动技术网 > 移动技术>移动开发>Android > Android开发 旋转屏幕导致Activity重建解决方法

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

2019年07月24日  | 移动技术网移动技术  | 我要评论
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|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对象没有销毁,但界面上的各种控件都被销毁重建了,你需要写额外的代码来恢复界面信息。
复制代码 代码如下:

@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();
}
}

官方的不建议使用这种方式处理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无疑是最省事的。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网