日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

Android?十六進制狀態(tài)管理實例詳解_Android

作者:入魔的冬瓜 ? 更新時間: 2022-11-16 編程語言

背景

最近需要實現(xiàn)一個狀態(tài)管理類:

  • 在多種場景下,控制一系列的按鈕是否可操作。
  • 不同場景下,在按鈕不可操作的時候,點擊彈出對應的Toast。
  • 隨著場景數(shù)量的增加,這個管理類的實現(xiàn),就可能會越來越復雜。

剛好看到大佬的文章,順便學習和實踐一下。
參考學習:就算不去火星種土豆,也請務(wù)必掌握的 Android 狀態(tài)管理最佳實踐

示例

還是用大佬那個例子。

例如,存在 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”。

實現(xiàn)思路

  • Kotlin中的位操作
shl(bits) – 左移位 
shr(bits) – 右移位
and(bits) – 與 
or(bits) – 或 
  • 定義多個十六進制的狀態(tài)常量,代表不同的狀態(tài)。
    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
  • 定義一個變量,用于存放當前的狀態(tài)。
  • 當狀態(tài)發(fā)生變化,需要切換狀態(tài)的時候,只需要去修改這個變量就行了。
    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
  • 定義模式狀態(tài)集,由狀態(tài)+多個禁用標志位組成。
    比如 MODE_A,就是在狀態(tài)為 STATUS_A 的時候,按鈕3禁用,那就將這兩個數(shù)值進行或運算,結(jié)果就是 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 進行存儲映射關(guān)系。

key 為對應狀態(tài)+禁用標志位的 或運算 結(jié)果。這樣的計算結(jié)果,是可以保證key是唯一的,不會出現(xiàn)重復的情況。

value 為對應的 Toast 文案。

只需要一個 HashMap 就可以實現(xiàn)所有的配置關(guān)系。

從代碼閱讀性來說,使用這樣的代碼進行配置,看起來也比較通俗易懂。
比如 Pair(STATUS_A or DISABLE_BTN_3, "A3"),就是代表在狀態(tài)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")
    )
  • 核心邏輯:判斷在當前模式下,按鈕是否可用。
    是否可用的判斷:判斷當前所處的狀態(tài),是否包含對應定義的禁用操作。
currentStatus and action !=0

若可操作,返回 true。

若不可操作,通過 currentStatus or action 的運算結(jié)果作為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 {
    //定義狀態(tài)常量
    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
    //定義模式狀態(tài)集
    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映射關(guān)系
    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")
    )
    //當前狀態(tài)
    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)
    }

輸出測試結(jié)果

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進制多狀態(tài)管理本質(zhì)上是二進制管理,即‘1’所處的位數(shù)。
  • 比如上面定義的各種變量,都是通過1左移n位數(shù)之后的結(jié)果。
  • 這樣能夠保證,多個不同變量的與運算、或運算結(jié)果,可以是唯一的。比如上面,用這個特性,用來做一層 Toast 文案的映射關(guān)系。

總結(jié)

  • 確實,像類似的場景,隨著業(yè)務(wù)迭代場景數(shù)增加,在沒有使用十六進制之前,整體的代碼可能是會比較復雜的。
  • 使用十六進制之后,可能需要多花一點時間,去理解一下十六進制相關(guān)的知識,但是在代碼實現(xiàn)上確實簡單了很多。

原文鏈接:https://juejin.cn/post/7147860255370641445

欄目分類
最近更新