Review同事代码时候,看到一段涉及到USB的逻辑代码,他是这样写的
private boolean isUsbConnected; private boolean isUsbConfigured; private boolean isUsbModeAccessory; private boolean isUsbModeAdb; private boolean isUsbModeMTP; ...
然后代码逻辑里是大量的成员变量的判断,显得非常臃肿而且难读懂,大量的if-else判断让代码逻辑很脆弱,稍微一个情况没考虑好就会出现难以排查的bug。
所以这种情况使用位掩码进行处理会更简单:
private static final int FLAG_USB_CONNECTED = 0x1; private static final int FLAG_USB_CONFIGURED = 0x1 << 1; private static final int FLAG_USB_MODE_ACY = 0x1 << 2; private static final int FLAG_USB_MODE_ADB = 0x1 << 3; private static final int FLAG_USB_MODE_MTP = 0x1 << 4; ... private int mUsbState; public void addUsbState(int flag) { mUsbState |= flag; } public void removeUsbState(int flag) { mUsbState &= ~flag; } public boolean isUsbStateEnable(int flag) { return (mUsbState & flag) == flag; }
简单分析一下这样写的好处:
FLAG_USB_CONNECTED = 0001 FLAG_USB_CONFIGURED = 0010 FLAG_USB_MODE_ACY = 0100 FLAG_USB_MODE_ADB = 1000
通过移位,使得每一位都有独立的代表的意义,1代表enable,0代表disable。
如果要 添加状态 (Java里int值默认赋值为0):
public void addUsbState(int flag) { mUsbState |= flag; }
假设添加accessory状态FLAG_USB_MODE_ACY
0000 |= 0100 -> 0100
所以mUsbState就是0100的状态了。
继续添加FLAG_USB_MODE_ADB状态
0100 |= 1000 -> 1100
public void removeUsbState(int flag) { mUsbState &= ~flag; }
比如接着上面移除FLAG_USB_MODE_ADB状态
1100 &= ~1000 -> 1100 &= 0111 -> 0100
如果移除一个不存在的状态比如FLAG_USB_CONFIGURED
0100 &= ~0010 -> 0100 &= 1101 -> 0100
可以看到并不会对当前状态造成任何影响。
最后看一下 检查状态 :
public boolean isUsbStateEnable(int flag) { return (mUsbState & flag) == flag; }
首先检查一下当前拥有的状态:
(0100 & 0100) == 0100 -> 0100 == 0100 -> true
可以检测到该状态。然后换一个状态:
(0100 & 1000) == 1000 -> 0000 == 1000 -> false
没有检测到该状态。
所以,通过三个简单的方法,就可以检查一个变量里保存的所有状态,避免了使用大量bool变量进行挨个检查。简化了代码,增加代码可读性,并且使代码更加稳定。