一直看不懂源码里的各种位运算,各种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 |
相同位的两个数字都为1,则为1;若有一个不为1,则为0。
举例: 00101
1
|
~
|
2
|
<<、>>
|
3
|
&
|
4
|
^
|
5
|
|
|
6
|
&=、^=、|=、<<=、>>=
|
注:位运算都是基于二进制来进行计算的。
看到此处,对于聪明的你想必已经能够理解并能够轻松的计算安卓中的各种flag的各种位运算了。
另:有人可能会问,直接位运算而不考虑flags的初始值吗?flags不同的初始值会不会对结果产生不同的影响?
你可以自己用笔算下,flags不同初始值的情况下,这个结果是不是一样。(我算了好几遍是一样的,囧~)
这篇博文只是当作学习笔记之用,以后碰到合适的心得体会也会继续写在csdn里,源于知识层面受限,有些地方说的不一定对,原谅我只是个努力学习中的小菜鸟。
end。