“我正在参加「启航计划」”
背景
最近需求完成一个状况办理类:
- 在多种场景下,操控一系列的按钮是否可操作。
- 不同场景下,在按钮不行操作的时分,点击弹出对应的Toast。
- 跟着场景数量的添加,这个办理类的完成,就或许会越来越复杂。
刚好看到大佬的文章,顺便学习和实践一下。
参考学习:就算不去火星种马铃薯,也请必须把握的 Android 状况办理最佳实践
示例
仍是用大佬那个比方。
例如,存在 3 种形式,和 3个按钮,按钮不行用的时分弹出对应的 Toast。
形式 A 下,要求 按钮1、按钮2 可用,按钮3不行用。点击按钮3,Toast 提示“A3”。
形式 B 下,要求 按钮2 可用,按钮1和按钮3不行用。点击按钮1,Toast 提示“B1”。点击按钮3,Toast 提示“B3”。
形式 C 下,要求 按钮1 可用,按钮2和按钮3不行用。点击按钮2,Toast 提示“C2”。点击按钮3,Toast 提示“C3”。
完成思路
- Kotlin中的位操作
shl(bits) – 左移位
shr(bits) – 右移位
and(bits) – 与
or(bits) – 或
- 界说多个十六进制的状况常量,代表不同的状况。
private const val STATE_IDIE = 1
private const val STATUS_A = 1 shl 1
private const val STATUS_B = 1 shl 2
private const val STATUS_C = 1 shl 3
- 界说一个变量,用于存放当时的状况。
当状况发生变化,需求切换状况的时分,只需求去修改这个变量就行了。
private var currentStatus = STATE_IDIE
//测验代码
private fun changeStateToA(){
changeStateToA = STATUS_A
}
- 界说多个十六进制的标志常量,代表对应的禁用操作。
比方 DISABLE_BTN_1,代表禁用按钮1。
//界说不行操作的一些行为
private const val DISABLE_BTN_1 = 1 shl 4
private const val DISABLE_BTN_2 = 1 shl 5
private const val DISABLE_BTN_3 = 1 shl 6
- 界说形式状况集,由状况+多个禁用标志位组成。
比方 MODE_A,便是在状况为 STATUS_A 的时分,按钮3禁用,那就将这两个数值进行或运算,成果便是 STATUS_A or DISABLE_BTN_3。
private const val MODE_A = STATUS_A or DISABLE_BTN_3
private const val MODE_B = STATUS_B or DISABLE_BTN_1 or DISABLE_BTN_3
private const val MODE_C = STATUS_C or DISABLE_BTN_2 or DISABLE_BTN_3
private val modeList = listOf(MODE_A, MODE_B, MODE_C)
- 界说按钮不行点击时的Toast案牍 ,运用 HashMap 进行存储映射联系。
- key 为对应状况+禁用标志位的 或运算 成果。这样的计算成果,是可以确保key是仅有的,不会出现重复的情况。
- value 为对应的 Toast 案牍。
- 只需求一个 HashMap 就可以完成一切的装备联系。
- 从代码阅读性来说,运用这样的代码进行装备,看起来也比较通俗易懂。
比方 Pair(STATUS_A or DISABLE_BTN_3, “A3”),便是代表在状况A的时分,禁用按钮3,点击按钮的时分弹的Toast案牍为 “A3”。
private val toastMap = hashMapOf(
Pair(STATUS_A or DISABLE_BTN_3, "A3"),
Pair(STATUS_B or DISABLE_BTN_1, "B1"),
Pair(STATUS_B or DISABLE_BTN_3, "B3"),
Pair(STATUS_C or DISABLE_BTN_2, "C2"),
Pair(STATUS_C or DISABLE_BTN_3, "C3")
)
- 中心逻辑:判别在当时形式下,按钮是否可用。
是否可用的判别:判别当时所处的状况,是否包含对应界说的禁用操作。
currentStatus and action !=0
若可操作,返回 true。
若不行操作,通过 currentStatus or action 的运算成果作为key,通过上面装备的 HashMap 调集,拿到对应的 Toast 案牍。
/**
* 判别当时某个行为是否可操作
*
* @return true 可操作;false,不行操作。
*/
private fun checkEnable(action: Int): Boolean {
val result = modeList.filter {
(it and currentStatus) != 0
&& (it and action) != 0
}
if (result.isNotEmpty()) {
println("result is false, toast:${toastMap[currentStatus or action]}")
return false
}
println("result is true")
return true
}
- 完整代码
object SixTeenTest {
//界说状况常量
private const val STATE_IDIE = 1
private const val STATUS_A = 1 shl 1
private const val STATUS_B = 1 shl 2
private const val STATUS_C = 1 shl 3
//界说不行操作的一些行为
private const val DISABLE_BTN_1 = 1 shl 4
private const val DISABLE_BTN_2 = 1 shl 5
private const val DISABLE_BTN_3 = 1 shl 6
//界说形式状况集
private const val MODE_A = STATUS_A or DISABLE_BTN_3
private const val MODE_B = STATUS_B or DISABLE_BTN_1 or DISABLE_BTN_3
private const val MODE_C = STATUS_C or DISABLE_BTN_2 or DISABLE_BTN_3
private val modeList = listOf(MODE_A, MODE_B, MODE_C)
//界说Toast映射联系
private val toastMap = hashMapOf(
Pair(STATUS_A or DISABLE_BTN_3, "A3"),
Pair(STATUS_B or DISABLE_BTN_1, "B1"),
Pair(STATUS_B or DISABLE_BTN_3, "B3"),
Pair(STATUS_C or DISABLE_BTN_2, "C2"),
Pair(STATUS_C or DISABLE_BTN_3, "C3")
)
//当时状况
private var currentStatus = STATE_IDIE
/**
* 判别当时某个行为是否可操作
*
* @return true 可操作;false,不行操作。
*/
private fun checkEnable(action: Int): Boolean {
val result = modeList.filter {
(it and currentStatus) != 0
&& (it and action) != 0
}
if (result.isNotEmpty()) {
println("result is false, toast:${toastMap[currentStatus or action]}")
return false
}
println("result is true")
return true
}
}
代码测验
fun main(args: Array<String>) {
//测验代码
currentStatus = STATUS_A
println("STATUS_A")
checkEnable(DISABLE_BTN_1)
checkEnable(DISABLE_BTN_2)
checkEnable(DISABLE_BTN_3)
currentStatus = STATUS_B
println("STATUS_B")
checkEnable(DISABLE_BTN_1)
checkEnable(DISABLE_BTN_2)
checkEnable(DISABLE_BTN_3)
currentStatus = STATUS_C
println("STATUS_C")
checkEnable(DISABLE_BTN_1)
checkEnable(DISABLE_BTN_2)
checkEnable(DISABLE_BTN_3)
}
输出测验成果
STATUS_A
result is true
result is true
result is false, toast:A3
STATUS_B
result is false, toast:B1
result is true
result is false, toast:B3
STATUS_C
result is true
result is false, toast:C2
result is false, toast:C3
十六进制
- 16进制多状况办理本质上是二进制办理,即‘1’所处的位数。
- 比方上面界说的各种变量,都是通过1左移n位数之后的成果。
- 这样可以确保,多个不同变量的与运算、或运算成果,可所以仅有的。比方上面,用这个特性,用来做一层 Toast 案牍的映射联系。
总结
- 的确,像类似的场景,跟着业务迭代场景数添加,在没有运用十六进制之前,整体的代码或许是会比较复杂的。
- 运用十六进制之后,或许需求多花一点时间,去理解一下十六进制相关的知识,但是在代码完成上的确简略了很多。