横竖屏切换导致页面频繁重启screenLayout解析

作者:BennuCTech 时间:2021-06-14 05:16:22 

前言

前几天多名用户反馈同一个问题,在小新平板上无法上网课,点击上课按钮后就退回到首页了。同事了解了一下发现小新平板现在销量特别好,于是赶紧申请了一台测试机打算看看到底是什么问题。

最后同事发现是screenLayout的问题,在manifest中为需要横竖屏切换的Acitivty配置screenLayout即可,如下:

<activity android:name=".MainActivity"
 android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
   android:launchMode="singleTask">
   <intent-filter>
      ...
   </intent-filter>
</activity>

我们之前android:configChanges配置是orientation|keyboardHidden|screenSize,缺少了screenLayout。

但是为什么在其他设备上没问题,唯独在小新平板上有问题呢?而且为什么添加了screenLayout就解决问题了,这其中的原理是什么?我非常好奇,于是自己研究了一下。

android:configChanges

首先我们要知道android:configChanges这个配置的作用,这里我们来看看官方的介绍:

列出 Activity 将自行处理的配置变更。在运行时发生配置变更时,默认情况下会关闭 Activity 并将其重启,但使用该属性声明配置将阻止 Activity 重启。相反,Activity 会保持运行状态,并且系统会调用其 onConfigurationChanged() 方法。

当Activity的配置发生变更时(如横竖屏切换),如果在android:configChanges中没有添加该配置,那么就会关闭并重启Activity,这时候debug会发现重新执行了onCreate。但是当我们添加了该配置,如果该配置发生变更,则不会重启Activity,会调用onConfigurationChanged()方法。

那么orientation就是对应着横竖屏切换,keyboardHidden则是软键盘弹出,screenSize则是屏幕尺寸改变。这么来看我们设置了orientation应该就可以了,但是官方在这里有一个提示,如下:

横竖屏切换导致页面频繁重启screenLayout解析

官方建议在设置orientation的同时设置screenSizescreenLayoutscreenSize我么可以理解,横竖屏切换时宽高会交换,那么screenLayout是指什么呢?

screenLayout

前面我们知道存在配置时会执行onConfigurationChanged(),这个函数的参数是Configuration类型的,这个类里保存着Activity的配置,我们来看看对screenLayout这个属性的描述:

/**
Bit mask of overall layout of the screen. Currently there are four fields:
The SCREENLAYOUT_SIZE_MASK bits define the overall size of the screen.
They may be one of SCREENLAYOUT_SIZE_SMALL, SCREENLAYOUT_SIZE_NORMAL,
SCREENLAYOUT_SIZE_LARGE, or SCREENLAYOUT_SIZE_XLARGE.
The SCREENLAYOUT_LONG_MASK defines whether the screen is wider/taller than normal.
They may be one of SCREENLAYOUT_LONG_NO or SCREENLAYOUT_LONG_YES.
The SCREENLAYOUT_LAYOUTDIR_MASK defines whether the screen layout is either LTR or RTL.
They may be one of SCREENLAYOUT_LAYOUTDIR_LTR or SCREENLAYOUT_LAYOUTDIR_RTL.
The SCREENLAYOUT_ROUND_MASK defines whether the screen has a rounded shape.
They may be one of SCREENLAYOUT_ROUND_NO or SCREENLAYOUT_ROUND_YES.
See Supporting Multiple Screens for more information.
**/
public int screenLayout;

可以看到screenLayout其实是承载着四个配置的:

  • 屏幕大小等级:有SCREENLAYOUT_SIZE_SMALL, SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_LARGESCREENLAYOUT_SIZE_XLARGE四种

  • 是否宽屏:屏幕是否比普通屏幕更宽或更高

  • 屏幕方向:屏幕是从左向右显示,还是从有向左显示

  • 是否是圆角屏:屏幕是否有圆角

通过将screenLayout于对应mask进行与运算就可以得到当前屏幕在该属性的值,比如:

screenLayout & SCREENLAYOUT_SIZE_MASK

就可以得到屏幕大小等级,一定是SCREENLAYOUT_SIZE_SMALL, SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_LARGESCREENLAYOUT_SIZE_XLARGE之一。

四个mask对应的二进制分别是:

  • SCREENLAYOUT_SIZE_MASK: 0000 0000 1111

  • SCREENLAYOUT_LONG_MASK: 0000 0011 0000

  • SCREENLAYOUT_LAYOUTDIR_MASK:0000 1100 0000

  • SCREENLAYOUT_ROUND_MASK: 0011 0000 0000

比如在我的测试机上得到的screenLayout是268435810,转成二进制就是

0001 0000 0000 0000 0000 0001 0110 0010

通过与四个mask分别计算得到SCREENLAYOUT_SIZE_NORMAL、SCREENLAYOUT_LONG_NO、SCREENLAYOUT_LAYOUTDIR_LTR和SCREENLAYOUT_ROUND_NO

而且无论横屏还是竖屏,我的测试机的screenLayout是不变的,所以即使在android:configChanges中没用添加screenLayout,横竖屏切换的时候也不会重启Activity,因为其他两个属性orientationscreenSize都添加了。

小新平板

那么为什么小新平板上会有不同的现象,在android:configChanges中添加screenLayout完后我在onConfigurationChanged函数中debug获取screenLayout值,发现横屏和竖屏这个值是不同的,分别是268435812和268435796。

通过与mask运算获取四个属性后对比发现,横竖屏切换后SCREENLAYOUT_LONG_NO变成了SCREENLAYOUT_LONG_YES,所以没添加screenLayout的时候就会导致Activity重启,添加后就可以了。

至于为什么重启Activity会导致回退到首页,其实是用户表述问题,现象是应用重启了。为什么应用会重启,这是因为我们的应用架构是单Activity的,页面由fragment承载。当从详情页打开上课页面时,会通过代码手动将竖屏切换到横屏(同时为了返回详情页时换回竖屏,在详情页手动切换回竖屏)。这时候Activity重启并以横屏状态恢复所有fragment,但是恢复详情页时候,又切换到竖屏,所以又重启;然后以竖屏状态恢复到上课页面,又进行了切换,于是死循环,最后系统将应用重启。

来源:https://juejin.cn/post/7210212440671387703

标签:screenLayout,横竖屏切换,页面重启
0
投稿

猜你喜欢

  • Java RabbitMQ高级特性详细分析

    2021-12-26 00:31:36
  • Android 字符串中某个字段可点击和设置颜色的方法

    2023-07-24 00:16:53
  • C#用户定义类型转换详解

    2022-06-07 11:44:32
  • java HashMap和HashTable的区别详解

    2023-08-10 18:41:56
  • JAVA8之函数式编程Function接口用法

    2022-01-04 04:03:04
  • Android 自定义密码输入框实现代码

    2023-02-11 09:18:40
  • JavaWeb Hibernate使用全面介绍

    2021-09-13 11:26:07
  • Android编程中File文件常见存储与读取操作demo示例

    2021-11-24 18:33:20
  • Android EditText限制输入整数和小数的位数的方法示例

    2022-12-23 05:15:30
  • C# 抓取网页内容的方法

    2022-09-13 04:50:10
  • 详解Android Gradle插件3.0挖坑日记

    2022-02-06 09:03:19
  • Android EditText限制输入字符类型的方法总结

    2023-10-11 15:48:19
  • Android实现图片点击放大

    2023-03-19 17:40:59
  • JAVA如何按字节截取字符串

    2023-11-25 13:31:41
  • Java编程基础测试题分享

    2023-11-27 22:14:58
  • 实例分析java开启线程的方法

    2022-06-24 19:54:00
  • 经典排序算法之冒泡排序(Bubble sort)代码

    2021-06-08 06:06:18
  • C# FileStream简单介绍和使用

    2023-07-05 23:04:05
  • Spring Boot接口限流的常用算法及特点

    2023-12-20 05:16:30
  • Spring请求参数校验功能实例演示

    2023-04-26 02:05:53
  • asp之家 软件编程 m.aspxhome.com