CrazyDailyQuestion icon indicating copy to clipboard operation
CrazyDailyQuestion copied to clipboard

2019-09-05:如何避免配置改变时Activity重建?

Open liu1813565583 opened this issue 6 years ago • 8 comments

liu1813565583 avatar Sep 04 '19 13:09 liu1813565583

在Amanifest中配置activity旋转屏幕不重新绘制

firehell avatar Sep 05 '19 01:09 firehell

所谓配置改变,是当程序运行过程中,一些设备的配置可能会发生改变,如:横竖屏切换、键盘的可用性等这样的事情发生的时候,activity在没有配置android:configChanges时会**重新启动。**并且会调用 onSaveInstanceState()onRestoreInstanceState() 方法。

如何避免重建

使用android:configChanges属性后,程序运行时如果配置发生变化时,不会重新启动activity即不会走2的流程,而是通知程序去调用onConfigurationChanged函数。例如:在横竖屏发生变化时,原来会重新启动activity,而定义了这个属性后,就不会重新启动activity了,而是调用onConfigrationChanged函数

ArtarisCN avatar Sep 05 '19 10:09 ArtarisCN

activity在系统配置改变的时候会重建,那么什么是系统配置呢?

系统配置

系统的配置在Configuration类中,有屏幕的方向,屏幕的尺寸等等

  • mcc: SIM卡唯一标示IMSI(国际移动用户识别码)中的国家代码,由三位数字组成,中国为460。此项标示mcc代码发生了改变
  • mnc: SIM卡的唯一标示IMSI(国际移动用户识别码)中的运营商代码,由2位数字组成,中国移动TD系统为00,中国联通为01,此项标示mnc发生改变
  • locale:设备的本地位置发生了改变,一般指切换了系统语言。
  • touchscreen:触屏发生了改变
  • keyboard:键盘类型发生了改变,比如使用了外接键盘
  • keyboardHidden:键盘的可访问性发生了改变,比如用户调出了键盘
  • navigation:系统导航发生了改变,比如采用了轨迹导航,这个有点费解,很难发生,可以忽略它。
  • srceenLayout:屏幕布局发生了改变,很可能是激活了另外一个显示设备
  • frontScale:系统字体缩放比例发生了变化,比如用户选择了一个新字号
  • uiMode:用户界面模式发生了改变,比如是否开启了夜间模式(API8新加)
  • orientation:屏幕方向发生了改变,这个是最常用的,比如旋转了手机屏幕
  • sreenSize:当屏幕尺寸信息发生改变,当选装设备时,屏幕尺寸会发生改变,这个选项比较特殊,它和编译选项有关,当编译选项中的minSdkVersion 和 targetSdkVersion均低于13时,此选项不会到时Activity重启,负责Activity将重启(api13)添加
  • smallScreenSize:设备的物理尺寸发生改变,这个项目和屏幕的方向没关系,仅仅表示在实习的物理屏幕的尺寸发生改变的时候,比如用户切换到了外部的显示设备,这个选项和srceenSize一样,当编译选项中中的* * minSdkVersion和targetSdkVersion均低于13时,此选项不会导致Activity重启,负责将导致Activity重启(API13新添加)
  • layoutDirection:当布局发生变化,这个属性用的比较少,正常情况下无须修改布局的layoutDirection属性(API17新添加) 上面列出的项目很多,其实我们常用的就 locale、orientation 和 keyboardHidden这三项。

解决系统配置改变activity重建问题

当我们想要这些配置改变的时候activity不被重建,那么我们可以在AndroidManfest.xml文件中的对应activity标签中添加属性:

       <activity android:name=".MainActivity"
               android:configChanges="orientation|sreenSize"  //添加这句
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

上边添加的属性,可以防止屏幕方向发生变化的时候activity重建。

gys0000 avatar Sep 05 '19 10:09 gys0000

之所以避免重建是因为重建会造成: 1、资源浪费(CPU、内存、网络等等); 2、逻辑复杂,本来一个简单的界面如果要兼容重建的情况逻辑就会变得复杂; 但是有些时候重建是有必要,比如横竖屏布局不一致等,我们没法解决第一个问题,但是我们可以用Android Jetpack架构组件之 ViewModel来解决逻辑复杂问题,它不会因为Activity被销毁而销毁,所以可以缓存页面操作过程中的数据,我们只需要在对应的onCreate或者onSaveInstanceState()重新绑定数据就好了。

chinwetang avatar Sep 05 '19 12:09 chinwetang

设备进行横竖屏切换时

如果不手动配置Activity configChanges属性,系统默认对Activity进行销毁重建操作。 API13以下,Activity configChanges属性中含有orientation即可避免Activity销毁重建。 API13及以上,Activity configChanges属性中同时含有orientation和screenSize即可避免Activity销毁重建。

liu1813565583 avatar Sep 05 '19 14:09 liu1813565583

在AndroidManifest里相应的界面配置configChanges。这样当配置改变时,就不会重建了。回调onConfigurationChanged。我们可以做一事相关的事情。

rainbow7 avatar Sep 05 '19 23:09 rainbow7

在索尼电视上BRAVIA 8K VH21,插入遥控器usb,或者拔掉也会触发重建

df13954 avatar Jan 22 '25 07:01 df13954

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

MicroKibaco avatar Jan 22 '25 07:01 MicroKibaco