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变量进行挨个检查。简化了代码,增加代码可读性,并且使代码更加稳定。