一直看不懂源码里的各种位运算,各种flag与非或非的,头大。
View里面有各种状态,都是用flag常量来标记的,然后用一个成员变量跟这些值通过位运算,来判断view当前的状态。
奈何在学校的时候没有好好学,各种知识都不记得了,今天重温Handler那块的源码时,突然有了灵感。
MessageQueue里面有个next方法,从消息队列中死循环不停取出消息,当然这个跟我要讲的内容无关,我贴出来是因为我是从这个方法中得到灵感的。
这个方法的22行有一句msg.markInUse();顾名思义,是调用msg的方法将该对象标记为正在使用。
final Message next() {
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(mPtr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
final Message msg = mMessages;
if (msg != null) {
final long when = msg.when;
if (now >= when) {
mBlocked = false;
mMessages = msg.next;
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
msg.markInUse();
return msg;
} else {
nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
}
} else {
nextPollTimeoutMillis = -1;
}
// If first time, then get the number of idlers to run.
if (pendingIdleHandlerCount < 0) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount == 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
那么markInUse方法的内容又是什么呢?
void markInUse() {
flags |= FLAG_IN_USE;
}
很简单的一句话,就是一句或运算。与之对应的获取该标记的方法是isInUse,方法如下:
boolean isInUse() {
return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
}
为什么相等呢?先来看看位运算的基本知识。(感谢度娘带我回顾了一遍位运算。)
运算符号
含义 | Pascal语言 | C语言 | Java |
---|---|---|---|
按位与 | a and b | a & b | a & b |
按位或 | a or b | a | b | a | b |
按位异或 | a xor b | a ^ b | a ^ b |
按位取反 | not a | ~a | ~a |
左移 | a shl b | a << b | a << b |
带符号右移 | a shr b | a >> b | a >> b |
无符号右移 | | | a>>> b |
运算说明
and运算
相同位的两个数字都为1,则为1;若有一个不为1,则为0。
举例: 00101
or运算
xor运算
not运算
shl运算
shr运算
优先级
1
|
~
|
2
|
<<、>>
|
3
|
&
|
4
|
^
|
5
|
|
|
6
|
&=、^=、|=、<<=、>>=
|
注:位运算都是基于二进制来进行计算的。
看到此处,对于聪明的你想必已经能够理解并能够轻松的计算安卓中的各种flag的各种位运算了。
另:有人可能会问,直接位运算而不考虑flags的初始值吗?flags不同的初始值会不会对结果产生不同的影响?
你可以自己用笔算下,flags不同初始值的情况下,这个结果是不是一样。(我算了好几遍是一样的,囧~)
这篇博文只是当作学习笔记之用,以后碰到合适的心得体会也会继续写在csdn里,源于知识层面受限,有些地方说的不一定对,原谅我只是个努力学习中的小菜鸟。
end。