工控智汇

工控智汇

Android 十六进制状态管理实战

admin 115 107
背景

最近需要实现一个状态管理类:

在多种场景下,控制一系列的按钮是否可操作。

随着场景数量的增加,这个管理类的实现,就可能会越来越复杂。

示例

还是用大佬那个例子。
例如,存在3种模式,和3个按钮,按钮不可用的时候弹出对应的Toast。


实现思路

Kotlin中的位操作

shl(bits)–左移位shr(bits)–右移位and(bits)–与or(bits)–或

定义多个十六进制的状态常量,代表不同的状态。

privateconstvalSTATE_IDIE=1privateconstvalSTATUS_A=1shl1privateconstvalSTATUS_B=1shl2privateconstvalSTATUS_C=1shl3

定义一个变量,用于存放当前的状态。
当状态发生变化,需要切换状态的时候,只需要去修改这个变量就行了。

privatevarcurrentStatus=STATE_IDIE//测试代码privatefunchangeStateToA(){changeStateToA=STATUS_A}

定义多个十六进制的标志常量,代表对应的禁用操作。
比如DISABLE_BTN_1,代表禁用按钮1。

//定义不可操作的一些行为privateconstvalDISABLE_BTN_1=1shl4privateconstvalDISABLE_BTN_2=1shl5privateconstvalDISABLE_BTN_3=1shl6

定义模式状态集,由状态+多个禁用标志位组成。
比如MODE_A,就是在状态为STATUS_A的时候,按钮3禁用,那就将这两个数值进行或运算,结果就是STATUS_AorDISABLE_BTN_3。

privateconstvalMODE_A=STATUS_AorDISABLE_BTN_3privateconstvalMODE_B=STATUS_BorDISABLE_BTN_1orDISABLE_BTN_3privateconstvalMODE_C=STATUS_CorDISABLE_BTN_2orDISABLE_BTN_3privatevalmodeList=listOf(MODE_A,MODE_B,MODE_C)

key为对应状态+禁用标志位的或运算结果。这样的计算结果,是可以保证key是唯一的,不会出现重复的情况。

value为对应的Toast文案。

只需要一个HashMap就可以实现所有的配置关系。

从代码阅读性来说,使用这样的代码进行配置,看起来也比较通俗易懂。

privatevaltoastMap=hashMapOf(Pair(STATUS_AorDISABLE_BTN_3,"A3"),Pair(STATUS_BorDISABLE_BTN_1,"B1"),Pair(STATUS_BorDISABLE_BTN_3,"B3"),Pair(STATUS_CorDISABLE_BTN_2,"C2"),Pair(STATUS_CorDISABLE_BTN_3,"C3"))

核心逻辑:判断在当前模式下,按钮是否可用。
是否可用的判断:判断当前所处的状态,是否包含对应定义的禁用操作。

currentStatusandaction!=0

若可操作,返回true。
若不可操作,通过currentStatusoraction的运算结果作为key,通过上面配置的HashMap集合,拿到对应的Toast文案。

/***判断当前某个行为是否可操作**@returntrue可操作;false,不可操作。*/privatefuncheckEnable(action:Int):Boolean{valresult={(itandcurrentStatus)!=0(itandaction)!=0}if(()){println("resultisfalse,toast:${toastMap[currentStatusoraction]}")returnfalse}println("resultistrue")returntrue}

完整代码

objectSixTeenTest{//定义状态常量privateconstvalSTATE_IDIE=1privateconstvalSTATUS_A=1shl1privateconstvalSTATUS_B=1shl2privateconstvalSTATUS_C=1shl3//定义不可操作的一些行为privateconstvalDISABLE_BTN_1=1shl4privateconstvalDISABLE_BTN_2=1shl5privateconstvalDISABLE_BTN_3=1shl6//定义模式状态集privateconstvalMODE_A=STATUS_AorDISABLE_BTN_3privateconstvalMODE_B=STATUS_BorDISABLE_BTN_1orDISABLE_BTN_3privateconstvalMODE_C=STATUS_CorDISABLE_BTN_2orDISABLE_BTN_3privatevalmodeList=listOf(MODE_A,MODE_B,MODE_C)//定义Toast映射关系privatevaltoastMap=hashMapOf(Pair(STATUS_AorDISABLE_BTN_3,"A3"),Pair(STATUS_BorDISABLE_BTN_1,"B1"),Pair(STATUS_BorDISABLE_BTN_3,"B3"),Pair(STATUS_CorDISABLE_BTN_2,"C2"),Pair(STATUS_CorDISABLE_BTN_3,"C3"))//当前状态privatevarcurrentStatus=STATE_IDIE/***判断当前某个行为是否可操作**@returntrue可操作;false,不可操作。*/privatefuncheckEnable(action:Int):Boolean{valresult={(itandcurrentStatus)!=0(itandaction)!=0}if(()){println("resultisfalse,toast:${toastMap[currentStatusoraction]}")returnfalse}println("resultistrue")returntrue}}
代码测试
funmain(args:ArrayString){//测试代码currentStatus=STATUS_Aprintln("STATUS_A")checkEnable(DISABLE_BTN_1)checkEnable(DISABLE_BTN_2)checkEnable(DISABLE_BTN_3)currentStatus=STATUS_Bprintln("STATUS_B")checkEnable(DISABLE_BTN_1)checkEnable(DISABLE_BTN_2)checkEnable(DISABLE_BTN_3)currentStatus=STATUS_Cprintln("STATUS_C")checkEnable(DISABLE_BTN_1)checkEnable(DISABLE_BTN_2)checkEnable(DISABLE_BTN_3)}

输出测试结果

STATUS_Aresultistrueresultistrueresultisfalse,toast:A3STATUS_Bresultisfalse,toast:B1resultistrueresultisfalse,toast:B3STATUS_Cresultistrueresultisfalse,toast:C2resultisfalse,toast:C3
十六进制

16进制多状态管理本质上是二进制管理,即‘1’所处的位数。

比如上面定义的各种变量,都是通过1左移n位数之后的结果。

这样能够保证,多个不同变量的与运算、或运算结果,可以是唯一的。比如上面,用这个特性,用来做一层Toast文案的映射关系。

总结

确实,像类似的场景,随着业务迭代场景数增加,在没有使用十六进制之前,整体的代码可能是会比较复杂的。

使用十六进制之后,可能需要多花一点时间,去理解一下十六进制相关的知识,但是在代码实现上确实简单了很多。

作者:入魔的冬瓜
链接: