Android 十六进制状态管理实战

导读:本篇文章讲解 Android 十六进制状态管理实战,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

背景

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

  1. 在多种场景下,控制一系列的按钮是否可操作。
  2. 不同场景下,在按钮不可操作的时候,点击弹出对应的Toast。
  3. 随着场景数量的增加,这个管理类的实现,就可能会越来越复杂。

示例

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 进行存储映射关系。
  1. key 为对应状态+禁用标志位的 或运算 结果。这样的计算结果,是可以保证key是唯一的,不会出现重复的情况。
  2. value 为对应的 Toast 文案。
  3. 只需要一个 HashMap 就可以实现所有的配置关系。
  4. 从代码阅读性来说,使用这样的代码进行配置,看起来也比较通俗易懂。
    比如 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

十六进制

Android 十六进制状态管理实战

  • 16进制多状态管理本质上是二进制管理,即‘1’所处的位数。
  • 比如上面定义的各种变量,都是通过1左移n位数之后的结果。
  • 这样能够保证,多个不同变量的与运算、或运算结果,可以是唯一的。比如上面,用这个特性,用来做一层 Toast 文案的映射关系。

总结

  • 确实,像类似的场景,随着业务迭代场景数增加,在没有使用十六进制之前,整体的代码可能是会比较复杂的。
  • 使用十六进制之后,可能需要多花一点时间,去理解一下十六进制相关的知识,但是在代码实现上确实简单了很多。

作者:入魔的冬瓜
链接:https://juejin.cn/post/7147860255370641445
来源:稀土掘金

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/118823.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!