前提:
在开发人员没有明确指定屏幕方向并且没有设置android:configChanges时,横竖屏切换过程中,Activity的生命周期会重新加载,属于该Activity的Fragment的生命周期也会重新加载。
我在实际工作中碰到的故障是这样的:在当前Activity中用户输入了他的信息点击完成保存数据,在保存数据的同时为了增强用户体验,会有一个SimpleProgressDialog显示在用户界面上,但当在此保存的过程中,会出现该SimpleProgressDialog在屏幕上无法清除并且无法操作该应用的bug,通过阅读源代码发现,该SimpleProgressDialog是继承自DialogFragment的(查了一些资料也发现:谷歌官方推荐的DialogFragment来创建进度条对话框)。
经过一些测试之后,我得出的结论是当用户在保存数据并且该过程还没结束时进行横竖屏切换导致该Activity被销毁,从而导致该SimpleProgressDialog也被销毁,但是没能够及时调用dismiss方法来清除屏幕上的对话框,当横竖屏切换结束时,该Activity会重新加载,其上的SimpleProgressDialog也会被重新加载,会再次调用show方法创建第二个进度条对话框,在保存数据完成时,应用会执行dismiss方法清除第二次创建的进度条,由于创建第一个进度条的Fragment已被销毁,从而导致bug出现,无法清除该SimpleProgressDialog并且无法操作该应用。(由于是刚从象牙塔中出来,学校里一直只是用C++写一些小东西,没有做过java方面的开发,更不用说是Android的开发了,也没有想过毕业了要做Android的开发,只是阴差阳错的干起了移动应用的开发,说起来也是个小白,有写错的地方希望批评指正)。
我的有两个想法:
一个是在该保存方法save执行之前禁止该应用进行横竖屏切换,在保存完成之后,设置用户自己设定的是否可以转屏的操作。
第二个则是在横竖屏切换的过程中禁止该Activity生命周期的重新加载,从而也就能使该SimpleProgressDialog不会被创建两次了。
这两个想法的实现办法:
一、查了一些资料发现:不想让软件在横竖屏之间切换,最简单的办法就是在项目的AndroidManifest.xml中找到你所指定的activity中加上android:screenOrientation属性,他有以下几个参数:"unspecified""landscape""portrait""user""behind""sensor""nosensor"。也可以调用setRequestedOrientation()方法来动态设置屏幕的横竖屏切换参数。
当然这里只能选择setRequestedOrientation()方法了:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
save();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
很明显这不应该被用作首选的方法,太繁琐了,如果不加注释的话,还会让维护者一时摸不着头脑,莫名其妙的代码。
二、如何让Activity在横竖屏切换时不重新加载生命周期呢,查了一些资料发现:可以在AndroidManifest.xml中加入配置 android:configChanges="mcc|mnc|orientation|screenSize"这样在保存数据时进行横竖屏切换,Activity就不会被重新加载,前文的bug也没有再出现呢。
其中"mcc"是指国际移动用户识别码所属国家代号,设置该参数用于屏蔽sim被侦测到了,去更新mcc,从而导致的Activity重新加载;
"mnc"是指国际移动用户识别码的移动网号码,设置该参数用于屏蔽sim被侦测到了,去更新mnc,从而导致的Activity重新加载;
"orientation" 用于屏蔽屏幕方向改变了,从而导致的Activity重新加载;
"screenSize" 用于屏蔽屏幕大小改变了,从而导致的Activity重新加载。
在Android4.0以后要想屏蔽屏幕方向改变导致的Activity生命周期重新加载,需要设置orientation|screenSize。
简单的一个问题,花了我好多时间来解决,不过当解决该问题的时候还是有一种满足感和自豪感。