我知道Android会破坏当前活动并重新创建它,因为设备配置在运行时已更改。
但设计此类行为背后的理由是什么?
我的意思是为什么要销毁和重新创建当前的活动。 如果不是这样的话会有任何缺点吗?
答案 0 :(得分:4)
首先,让我们看看what Google has to say about it:
重新启动行为旨在通过使用与新设备配置匹配的备用资源自动重新加载应用程序,帮助您的应用程序适应新配置。
那是什么意思? Android设计人员认为(大多数*)精心设计的应用程序应该具有针对不同配置定制的资源。例如,大多数应用程序具有不同的纵向和横向模式布局。不仅如此,语言变化等内容可能需要不同的字符串等。
要处理这个问题,可以采用(至少)两种方法之一。重启整个事情,或者只是加载新资源。
只加载新资源会给开发人员(IMO)带来额外负担,迫使他们更深入地思考确切需要哪些资源,并使用某种onConfigChanged()
方法重新加载它们。如果你错过一个怎么办?如果你没有按照以前的顺序加载它们怎么办?这会改变一切吗?
通过重新启动整个过程,它确保您从一个空白的平板开始,并且应用程序应该完全按照您从该配置首先开始的方式(您在技术上做到了)。
*当然,规则有例外。例如,锁定在一个方向的任何应用程序都不关心方向更改。一些企业应用程序不需要多种语言等。目标是使90%而不是10%变得容易。
答案 1 :(得分:3)
但设计此类行为背后的理由是什么?
配置更改通常意味着您需要不同的资源:
Android无法替换所有资源用途,除非强制您重新加载所有资源。
如果不是这样的话会有任何缺点吗?
缺点是开发人员会搞砸它。
它们将阻止某些配置更改破坏和重新创建活动,但不会阻止其他配置更改,因此当发生其他配置更改时,它们的应用程序会中断。因此,例如,当用户将设备放入桌面底座时,应用程序可能会中断,因为开发人员将android:configChanges=screenSize|orientation
添加到清单中并完全忽略其他配置更改方案。
他们会错过资源。例如,“只是添加到清单android:configChanges = screenSize | orientation into activity tag”实际上不会修复UI以考虑屏幕方向,因此UI可能会在底部被截断。或者,开发人员忘记重新加载每个字符串资源,因此现在通过更改区域设置,UI具有一组混合语言。等等。
答案 2 :(得分:0)
生命周期流背后的原因是android提供了基于设备配置使用特定资源的机制。
例如,如果您想在纵向模式下使用一个布局文件,在横向模式下使用不同的布局文件,则使用纵向模式实例化的活动将无法访问园景文件,除非它通过重建自己的过程。然后,您可以设计UI控制器(无论是活动还是片段)来扩展正确的视图,并根据配置使用某些渲染逻辑。 Android为您提供了挂钩,用于保存在一个配置中加载的数据或状态,然后在配置更改时重新加载。
95%的情况下,大多数应用程序/开发人员都不使用此模式,并且最终会使您的代码在配置更改中保存对象状态方面更加冗长,但android也提供了一种机制为你处理。
Fragment#setRetainInstance是一种机制,用于将UI或数据的状态存储在片段中,当活动旋转时,它将在旋转时使用相同的片段。模式就是这样
//in onCreate in your activity
Fragment myFrag = getSupportFragmentManager().findFragmentByTag("MY_FRAGMENT_TAG");
if(myFrag == null) {
myFrag = new MyFragment();
myFrag.setRetainInstanceState(true);
getSupportFragmentManager().beginTransaction().
.replace(android.R.id.content, myFrag, "MY_FRAGMENT_TAG");
.commit();
}
当活动再次运行onCreate时,它将调用findFragmentByTag并且它不会为null并且旧片段仍将附加到UI
答案 3 :(得分:-1)
只需添加清单android:configChanges = screenSize | orientation into activity tag