public static final int VISIBLE = 0x00000000;
public static final int INVISIBLE = 0x00000004;
public static final int GONE = 0x00000008;
static final int VISIBILITY_MASK = 0x0000000C;
判断 flags 时是这么判断的:if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE)
为什么不这样判断:if ((child.mViewFlags & VISIBLE) == VISIBLE)
1
yongfrank 2022-12-04 18:34:21 +08:00 1
刚刚用 ChatGPT 出了一个答案
在计算机程序中,通过 mask 的位运算来判断 flag 通常是为了将 flag 的多个属性(例如是否启用、是否可读、是否可写等)用一个整数来表示。 在位运算中,通过与掩码( mask )进行与(&)运算可以判断 flag 的某一位是否被设置为 1 。例如,如果要判断 flag 的第 3 位是否被设置为 1 ,可以将 flag 与掩码 0b100 进行与运算,如果结果为 0 则表示 flag 的第 3 位被设置为 0 ,否则表示 flag 的第 3 位被设置为 1 。 使用 mask 的位运算来判断 flag 的好处在于它可以节省存储空间,将多个属性用一个整数来表示,而不需要单独开辟多个变量来存储每个属性。例如,如果使用多个变量来表示 flag 的多个属性,则需要开辟多个 8 位的存储空间,而如果使用 mask 的位运算,则只需要开辟一个 8 位的存储空间就可以表示多个属性。 |
2
hello2090 2022-12-04 18:34:47 +08:00
你这个 if ((child.mViewFlags & VISIBLE) == VISIBLE) 不是 永远 true 吗?
|
4
Cat7373 2022-12-04 18:39:19 +08:00
@hello2090 #2 并不是的,MASK 说明了 0x0C 这一位表示是否可视,VISIBLE 的值说明了这一位是 0 时是可视,是 1 时是不可视,即 MASK 表示哪一位代表这个开关,VISIBLE 表示值是什么的时候代表什么结果
|
5
fhj OP @yongfrank 谢谢,刚才看到一段这样的代码,这或许就是 mask 的作用把
switch (mViewFlags&VISIBILITY_MASK) { case VISIBLE: out.append('V'); break; case INVISIBLE: out.append('I'); break; case GONE: out.append('G'); break; default: out.append('.'); break; } |
6
cxtrinityy 2022-12-04 18:40:40 +08:00
VISIBILITY_MASK 是 0x0000000C -- 二进制是 1100
invisible 是 0x00000004 -- 二进制是 0100 gone 是 0x00000008 -- 二进制是 1000 也就是 gone 和 invisible 是用不同位来表示, visible 要保证 gone 和 invisible 都未设置, 一次位运算就能验证两个设置 |
7
Cat7373 2022-12-04 18:41:29 +08:00
@Cat7373 #4 修正一下,0x0C 有两个 bit 位为 1 ,因此这两个 bit 位任意一个为 1 ,此判断结果都为不可视,均为 0 ,才为可视,具体代码设计中,这两个 bit 位各代表什么意思这里看不出,但设计上可以实现,有两个各代表某个意思的开关,任意一个打开,都代表不可视
|
8
Cat7373 2022-12-04 18:42:03 +08:00
@cxtrinityy #6 啊这,没注意到上面两个常量,丢人了丢人了
|
11
DeweyReed 2022-12-04 18:48:15 +08:00
public static final int VISIBLE = 0x00000000;
|
12
jeesk 2022-12-04 21:58:02 +08:00
最近自己优化内存用到的代码直接贴出来给你了。
``` object BitStatesUtils { const val isFavorite = (1L shl 0).toByte() const val isDownload = (1L shl 1).toByte() const val isTrashed = (1L shl 2).toByte() public const val SIZE_BITS: Byte = 0 /** * @param states 所有状态值 * @param value 需要判断状态值 * @return 是否存在 */ fun hasState(states: Byte, value: Byte): Boolean { val byte = (states and value) as Byte return byte != SIZE_BITS } fun Byte.HasState(value: Byte): Boolean { return BitStatesUtils.hasState(this, value) } /** * @param states 已有状态值 * @param value 需要添加状态值 * @return 新的状态值 */ fun addState(states: Byte, value: Byte): Byte { return if (hasState(states, value)) { states } else (states or value) } fun Byte.AddState(value: Byte): Byte { return addState(this, value) } /** * @param states 已有状态值 * @param value 需要删除状态值 * @return 新的状态值 */ fun removeState(states: Byte, value: Byte): Byte { return if (!hasState(states, value)) { states } else (states xor value) } } ``` |
13
FranzKafka95 2022-12-04 23:04:47 +08:00 via Android
嵌入式里很常见的操作,尤其是当你需要用一个 bit 表示一个状态,同时又想节省空间时,位操作就非常有必要了。
|
14
Building 2022-12-04 23:11:22 +08:00 via iPhone
Mask 和 Optional Value 就像锁和钥匙,你可以把运算过程想像成把钥匙插入锁里面,全部凹槽都配平才能打开
|
15
lysS 2022-12-05 11:53:11 +08:00
用位表示 flag ,是为了正交隔离
|