java位状态_Java使用位域进行多标记(状态)管理

Android中位域的应用

在Android中,我们会经常用到或者看到以下这样的代码 :

public class ExampleUnitTest {

@Test

public void gravityTest(LayoutParams params) {

// 视图在layout中右下角显示

params.gravity = Gravity.RIGHT | Gravity.BOTTOM;

}

@Test

public void intentFlagTest(Intent intent) {

// 清空任务栈中所有旧的activity

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK

| Intent.FLAG_ACTIVITY_CLEAR_TASK);

// 如果activity已存在于栈中,清空该activity之上的所有任务

intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP

| Intent.FLAG_ACTIVITY_CLEAR_TOP);

}

@Test

public void windowMangerFlags(WindowManager.LayoutParams params) {

// 不拦截视图以外的事件,在锁屏中显示

params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL

| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;

}

}

通过一个 int字段,来添加多个 标志或者状态. 一个int字段,能够管理多个标记(状态)值.

如此神奇的操作怎样实现的呢? 答案就是通过位运算来实现.

位操作基础

java中提供的基础位运算符有 与(&),或(|),非(~),异或(^),左移<

右移(>>)和无符号右移(>>>).

除了位非(~)是一元操作符外,其它的都是二元操作符。

下面只介绍本文中,使用到的位操作

按位与

A & B : A和B对应的二进制数位都为1时,结果才为1,其他情况为0.

A = 001101 // 13

B = 100101 // 37

A & B = 000101 // 5

按位或

A | B : A和B对应的二进制数位都为0时,结果才为0,其他情况为1.

A = 001101 // 13

B = 100101 // 37

A | B = 101101 // 45

按位非

~A : 将a的二进制表示每一位进行取反操作,0变1,1变0.

相当于相反数 - 1

A = 001101 // 13

~A = 11111111111111111111111111110010 // int32位,补码表示,第一位为符号位

// 根据上诉补码转原码为

// 10000000000000000000000000001110 // -14

左移操作

A << B:将A的二进制表示的每一位向左移B位,左边超出的位截掉,右边不足的位补0。

在取值范围内,移动一位相当于乘2.

A = 001101 // 13

A << 1 = 011010 // 26

原理与实践

通常情况下,如果多个状态或者标记相互之间有关联, 如布局方向,上下左右,左上,居中 ... 等.我们可能会为每一个标记设置一个变量.

boolean left = false;

boolean right = false;

...

void setLeft(boolean b);

void setRight(boolean b);

...

这种情况下, 有4个标记相互关联,并且能产生新的标记,那么我们就需要设置4个标记变量,然后只能通过一系列的set方法来转换状态.如

v.setLeft(true);

v.setRight(true);

这样就会使得,各个状态不易维护和判断,状态越多,情况越复杂,代码会显得冗长难以维护.

像这种,独立状态(标记)之间相互组合可以产生新的状态(标记),且每个独立状态(标记)只有true或者false值的,我们可以使用位域的概念来管理这些状态.

它的核心思想就是将, int 数值看做是 二进制数位表示.如果有四个状态就可以像这样 0000,用四位二进制表示,每一个二进制位都可以表示一种状态. 然后通过 位运算,来提取或添加标记位.四位对应的组合状态有16个. 而我们,只需要通过一个int变量就能够管理这些状态.

当参与的状态(标记)越多时,如果使用单独的标记变量,就需要生成越多的变量,而用位域,这种独立状态为不管有多少个,都可以用一个变量表示.int类型最多存放32个独立状态

下面我们来看具体实现.(简单的模仿Gravity类的一部分功能)

public class Gravity {

// 二进制表示 0001

public static final int LEFT = 1;

// 二进制表示 0010

public static final int RIGHT = LEFT << 1;

// 二进制表示 0100

public static final int TOP = LEFT << 2;

// 二进制表示 1000

public static final int BOTTOM = LEFT << 3;

// 水平居中, 二进制表示 0011

public static final int HORIZONTAL_CENTER = LEFT | RIGHT;

// 垂直居中, 二进制表示 1100

public static final int VERTICAL_CENTER = TOP | BOTTOM;

// 居中, 二进制表示 1111

public static final int CENTER = HORIZONTAL_CENTER | VERTICAL_CENTER;

// 默认左上角, 二进制表示 0101

public static final int DEFAULT = LEFT | TOP;

// 存放标志位

private int mFlags = DEFAULT;

// 设置标记位,会清除原来的标记

public void setFlags(int flags) {

mFlags = flags;

}

// 添加标记位,在原来的基础上添加

public void addFlags(int flags) {

mFlags |= flags;

}

// 清除指定的标记

public void clearFlags(int flags) {

mFlags &= ~flags;

}

// 清除所有标记,设为默认

public void clears() {

mFlags = DEFAULT;

}

// 判断是否存在指定的标记

public boolean hasFlags(int flags) {

return (mFlags & flags) == flags;

}

// 判断是否 只有指定的标记

public boolean onlyFlags(int flags) {

return mFlags == flags;

}

public void apply() {

String des = "左上角";

if (hasFlags(CENTER)) {

des = "整体居中";

} else if (hasFlags(HORIZONTAL_CENTER)) {

if (hasFlags(BOTTOM)) des = "水平居中,竖直向下";

else des = "水平居中,竖直向下";

} else if (hasFlags(VERTICAL_CENTER)) {

if (hasFlags(RIGHT)) des = "竖直居中,水平向右";

else des = "竖直居中,水平向左";

} else if (hasFlags(LEFT | BOTTOM)) {

des = "左下角";

} else if (hasFlags(RIGHT | TOP)) {

des = "右上角";

} else if (hasFlags(RIGHT | BOTTOM)) {

des = "右下角";

}

System.out.println("你选择的布局是 : " + des);

}

}

具体的调用实现 :

public class Main {

public static void main(String[] args) {

Gravity gravity = new Gravity();

// 设置为 右下角

gravity.setFlags(Gravity.BOTTOM | Gravity.RIGHT);

gravity.apply();

// 添加 left后,变为 水平居中,竖直向下

gravity.addFlags(Gravity.LEFT);

gravity.apply();

// 判断是否 水平居中, 返回为 true

gravity.hasFlags(Gravity.HORIZONTAL_CENTER);

// 添加top后,变为 整体居中了

gravity.addFlags(Gravity.TOP);

gravity.apply();

// 删掉 bottom和left 之后,变为右上角了

gravity.clearFlags(Gravity.BOTTOM | Gravity.LEFT);

gravity.apply();

}

}

// 结果

你选择的布局是 : 右下角

你选择的布局是 : 水平居中,竖直向下

你选择的布局是 : 整体居中

你选择的布局是 : 右上角

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值