在android的系统类中经常可以看到巧妙的位运算,下面我们来学习一下。
例如View中的flag
static final int PFLAG_WANTS_FOCUS = 0x00000001;
/** {@hide} */
static final int PFLAG_FOCUSED = 0x00000002;
/** {@hide} */
static final int PFLAG_SELECTED = 0x00000004;
/** {@hide} */
static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
/** {@hide} */
static final int PFLAG_HAS_BOUNDS = 0x00000010;
/** {@hide} */
static final int PFLAG_DRAWN = 0x00000020;
/**
* When this flag is set, this view is running an animation on behalf of its
* children and should therefore not cancel invalidate requests, even if they
* lie outside of this view's bounds.
*
* {@hide}
*/
static final int PFLAG_DRAW_ANIMATION = 0x00000040;
/** {@hide} */
static final int PFLAG_SKIP_DRAW = 0x00000080;
/** {@hide} */
static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
/** {@hide} */
static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
/** {@hide} */
static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
/** {@hide} */
static final int PFLAG_FORCE_LAYOUT = 0x00001000;
/** {@hide} */
static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
private static final int PFLAG_PRESSED = 0x00004000;
/** {@hide} */
static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
/**
* Flag used to indicate that this view should be drawn once more (and only once
* more) after its animation has completed.
* {@hide}
*/
static final int PFLAG_ANIMATION_STARTED = 0x00010000;
private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
/**
* Indicates that the View returned true when onSetAlpha() was called and that
* the alpha must be restored.
* {@hide}
*/
static final int PFLAG_ALPHA_SET = 0x00040000;
/**
* Set by {@link #setScrollContainer(boolean)}.
*/
static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
/**
* Set by {@link #setScrollContainer(boolean)}.
*/
static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
/**
* View flag indicating whether this view was invalidated (fully or partially.)
*
* @hide
*/
static final int PFLAG_DIRTY = 0x00200000;
/**
* Mask for {@link #PFLAG_DIRTY}.
*
* @hide
*/
static final int PFLAG_DIRTY_MASK = 0x00200000;
/**
* Indicates whether the background is opaque.
*
* @hide
*/
static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
/**
* Indicates whether the scrollbars are opaque.
*
* @hide
*/
static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
/**
* Indicates whether the view is opaque.
*
* @hide
*/
static final int PFLAG_OPAQUE_MASK = 0x01800000;
/**
* Indicates a prepressed state;
* the short time between ACTION_DOWN and recognizing
* a 'real' press. Prepressed is used to recognize quick taps
* even when they are shorter than ViewConfiguration.getTapTimeout().
*
* @hide
*/
private static final int PFLAG_PREPRESSED = 0x02000000;
/**
* Indicates whether the view is temporarily detached.
*
* @hide
*/
static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
/**
* Indicates that we should awaken scroll bars once attached
*
* PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
* during window attachment and it is no longer needed. Feel free to repurpose it.
*
* @hide
*/
private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
/**
* Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
* @hide
*/
private static final int PFLAG_HOVERED = 0x10000000;
/**
* Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked.
*/
private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000;
/** {@hide} */
static final int PFLAG_ACTIVATED = 0x40000000;
/**
* Indicates that this view was specifically invalidated, not just dirtied because some
* child view was invalidated. The flag is used to determine when we need to recreate
* a view's display list (as opposed to just returning a reference to its existing
* display list).
*
* @hide
*/
static final int PFLAG_INVALIDATED = 0x80000000;
这些flag都是int类型的,并且都是以0x开头的也就是十六进制数。这些flag转为二进制后有个特点只有一位为1,其余都是0
// 0000 0000 0000 0000 0000 0000 0000 0000 //二进制转为十进制0
// 代表什么标志位都没有
int flag_mask = 0x00000000; //十六进制0的写法
// 0000 0000 0000 0000 0000 0000 0000 0001 //二进制转为十进制1 等同于1<<0
int a1 = 0x00000001; //十六进制1的写法
// 0000 0000 0000 0000 0000 0000 0000 0010 //二进制转为十进制2 等同于1<<1
int a2 = 0x00000002; //十六进制2的写法
// 0000 0000 0000 0000 0000 0000 0000 0100 //二进制转为十进制4 等同于1<<2
int a3 = 0x00000004; //十六进制4的写法
// 0000 0000 0000 0000 0000 0000 0000 1000 //二进制转为十进制8 等同于1<<3
int a4 = 0x00000008; //十六进制8的写法
// 0000 0000 0000 0000 0000 0000 0001 0000 //二进制转为十进制16 等同于1<<4
int a5 = 0x00000010; //十六进制16的写法
// 0000 0000 0000 0000 0000 0000 0010 0000 //二进制转为十进制32 等同于1<<5
int a6 = 0x00000020; //十六进制32的写法
1 添加标志:
//现在我们往flag_mask添加标志a1,a4
flag_mask |= a1;
flag_mask |= a4;
Log.i("zhangqing","添加标志:"+Integer.toBinaryString(flag_mask));
// 分析:
// flag_mask=00000000 00000000 00000000 00000000 int是4字节,32位的
// a1 =00000000 00000000 00000000 00000001
// 按位或操作的结果:
// result =00000000 00000000 00000000 00000001
// a4 =00000000 00000000 00000000 00001000
// result1 =00000000 00000000 00000000 00001001
// 所以通过|操作符可以实现标志位的添加功能
运行结果:
结果转为十六进制0x00001001
2 提取标志
//提取标志
//提取的功能主要是用来判断某个标志位是否存在,是否已经设置了
boolean isA1Seted = (flag_mask & a1) == a1;
Log.i("zhangqing", "a1是否设置:" + isA1Seted);
boolean isA4Seted = (flag_mask & a4) == a4;
Log.i("zhangqing", "a4是否设置:" + isA4Seted);
boolean isA3Seted = (flag_mask & a3) == a3;
Log.i("zhangqing", "a4是否设置:" + isA3Seted);
// 分析:
// flag_mask=00000000 00000000 00000000 00001001 int是4字节,32位的
// a1 =00000000 00000000 00000000 00000001
// a4 =00000000 00000000 00000000 00001000
// a3 =00000000 00000000 00000000 00000100
// 通过按位于操作符&
// resultA1 =00000000 00000000 00000000 00000001
// resultA4 =00000000 00000000 00000000 00001000
// resultA3 =00000000 00000000 00000000 00000000
// 所以要提取某个标志位,然后判断是否存在就使用&操作符
3 删除标志
//删除标志
//有的时候我们会把某个标志从mask里面删除,该怎么操作呢?
flag_mask &= ~a1;
flag_mask &= ~a4;
Log.i("zhangqing", "删除后的结果flag_mask:" + Integer.toBinaryString(flag_mask));
// 分析:
// flag_mask=00000000 00000000 00000000 00001001 int是4字节,32位的
// ~a1 =11111111 11111111 11111111 11111110 按位取反的结果
// ~a4 =11111111 11111111 11111111 11110111 按位取反的结果
// 按位与&
// flag_mask=00000000 00000000 00000000 00001000
// flag_mask=00000000 00000000 00000000 00000000
// 最终结果把a1和a4都删除了
结果转为十六进制0x00000000
系统的源代码就是最好的老师,我们经常熟悉android源码,可以取其精华。