最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

務(wù)必掌握的Android十六進(jìn)制狀態(tài)管理最佳實(shí)踐

 更新時(shí)間:2022年09月27日 11:48:23   作者:KunMinX  
這篇文章主要為大家介紹了務(wù)必掌握的Android十六進(jìn)制狀態(tài)管理最佳實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

上周在掘金巧遇一篇 “用設(shè)計(jì)模式管理狀態(tài)” 文章,作為補(bǔ)充,在評(píng)論區(qū)安利我司封裝商業(yè)級(jí) SDK 時(shí)常用的 “十六進(jìn)制狀態(tài)管理機(jī)制”。

原以為無(wú)人對(duì)此感興趣,沒(méi)想到留言很快便收到文章作者回復(fù),且在評(píng)論區(qū)耐心和我探討設(shè)計(jì)模式 獨(dú)占式狀態(tài)機(jī) 和十六進(jìn)制 復(fù)合狀態(tài)管理 使用場(chǎng)景區(qū)別。

遺憾的是,通過(guò)評(píng)論區(qū)只言片語(yǔ),難讓人體會(huì) “十六進(jìn)制狀態(tài)管理” 真正魅力,

故今日我們以封裝商業(yè)級(jí) SDK 為例,拆解我們是如何使用十六進(jìn)制完成狀態(tài)管理,相信閱讀后你會(huì)豁然開(kāi)朗。

我和十六進(jìn)制的 “三次握手”

最初對(duì)十六進(jìn)制產(chǎn)生興趣,或說(shuō)知道它何時(shí)可派上用場(chǎng),是 2015 年觀看電影《火星救援》時(shí)發(fā)現(xiàn)。

為和 “遠(yuǎn)在 4 億公里外、電磁波需 40 分鐘才能完成一次完整請(qǐng)求響應(yīng)” 的地球通信,孑然一身主角 Mark 想到一辦法,即是通過(guò)十六進(jìn)制和 ACSII 碼表:

將字符轉(zhuǎn)換成字母 ,這樣地球上的人便可通過(guò)控制 “Mark 從沙漠中掏來(lái)的 1997 年服役的探路者號(hào)(PathFinder)” 攝像頭偏移角度,來(lái)指明一連串字符,從而 Mark 可將它們轉(zhuǎn)譯成英文。

第二次接觸十六進(jìn)制是在 2016 年,當(dāng)我閱讀 View/ViewGroup 源碼,發(fā)現(xiàn)狀態(tài)多通過(guò)十六進(jìn)制管理,但當(dāng)時(shí)因不知為何這么使用、這樣使用究竟有什么好處,也就沒(méi)大注意。

@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {
        // We're already in this state, assume our ancestors are too
        return;
    }
    if (disallowIntercept) {
        mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
    } else {
        mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
    }
    // Pass it up to our parent
    if (mParent != null) {
        mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
    }
}

直到 2017 年夏天,我和一位彼時(shí) 3 年經(jīng)驗(yàn)同事聯(lián)手完成核心項(xiàng)目重構(gòu)時(shí),因同事提出使用十六進(jìn)制管理狀態(tài),而親眼見(jiàn)證十六進(jìn)制在狀態(tài)管理方面絕佳優(yōu)勢(shì)。

為紀(jì)念這一分享,此后每當(dāng)有新同事入職,我提供的培訓(xùn)課程必包含十六進(jìn)制狀態(tài)管理。

使用十六進(jìn)制前的混沌世界

該項(xiàng)目有個(gè)需求:當(dāng)指定圖形編輯模式,圖形工具欄按鈕狀態(tài)需隨之發(fā)生改變。

例如,存在 3 種圖形編輯模式,和 8 個(gè)圖形編輯按鈕。

模式 A 下,要求 按鈕1、按鈕2、按鈕3 可用,其余按鈕禁用。

模式 B 下,要求 按鈕1、按鈕4、按鈕5、按鈕6 可用,其余按鈕禁用。

模式 C 下,要求 按鈕1、按鈕7、按鈕8 可用,其余按鈕禁用。

如是傳統(tǒng)方式編寫,我們勢(shì)必會(huì)在類中為 3 個(gè)模式定義 boolean 變量,為 8 個(gè)按鈕狀態(tài)定義 boolean 變量。

那么模式切換時(shí),就需將每個(gè)按鈕狀態(tài)的變量都 “清洗” 一遍。例如:

public void setModeA() {
    status1 = true;
    status2 = true;
    status3 = true;
    status4 = false;
    status5 = false;
    status6 = false;
    status7 = false;
    status8 = false;
}
public void setModeB() {
    status1 = true;
    status2 = false;
    status3 = false;
    status4 = true;
    status5 = true;
    status6 = true;
    status7 = false;
    status8 = false;
}
public void setModeC() {
    ...
}

當(dāng)日后模式變多、按鈕狀態(tài)變多,類中就會(huì)滿是這種 setMode 方法,看起來(lái)很蠢,且密密麻麻的 true、false 極易出錯(cuò)。

這是一點(diǎn)。

另一點(diǎn)是,如按鈕狀態(tài)是用 boolean 變量管理,那么狀態(tài)的存儲(chǔ)和讀取便難辦,

  • 每個(gè) boolean 變量都需轉(zhuǎn)換成 int 類型 0 或 1 存儲(chǔ)在數(shù)據(jù)庫(kù)中。
  • 數(shù)據(jù)庫(kù)需為每個(gè)狀態(tài)準(zhǔn)備一個(gè)字段。
  • 讀取時(shí)又需負(fù)責(zé)將每個(gè)狀態(tài)轉(zhuǎn)譯回 boolean。

這工作量很大,且日后每添加或修改一狀態(tài),數(shù)據(jù)庫(kù)都需新增或修改字段,十分低效和不安全。

十六進(jìn)制能很好解決這些問(wèn)題

十六進(jìn)制可做到:

  • 通過(guò)狀態(tài)集的注入,一行代碼即可完成模式切換。
  • 無(wú)論再多狀態(tài),都只需一個(gè)字段來(lái)存儲(chǔ)。狀態(tài)被存放在 int 類型狀態(tài)集中,可直接讀寫于數(shù)據(jù)庫(kù)。

十六進(jìn)制運(yùn)作機(jī)制

在具體了解十六進(jìn)制是怎么做到狀態(tài)管理最佳實(shí)踐前,我們先簡(jiǎn)單過(guò)一遍十六進(jìn)制本身運(yùn)作機(jī)制。

首先,在編程中,利用開(kāi)頭 0x 表示十六進(jìn)制數(shù)。

例如 0x0001,0x0002。

然后,十六進(jìn)制的計(jì)算,可借助二進(jìn)制 “按位計(jì)算” 方式理解。

二進(jìn)制存在 與、或、異或、取反 等操作:

a & b,a | b,a ^ b,~a

例如,十六進(jìn)制數(shù) 0x0004 | 0x0008,可理解為:

0100 
 |
1000
 =
1100

十六進(jìn)制 (0x0004 | 0x0008) & 0x0004 可得:

1100 
 &
0100
 =
0100

也即 “狀態(tài)集” 包含某狀態(tài)時(shí),再 & 該狀態(tài),便得非 0 結(jié)果。

于是,我們便可利用該特性完成狀態(tài)管理:

十六進(jìn)制狀態(tài)管理實(shí)戰(zhàn)

  • 首先定義一個(gè) “狀態(tài)集” 變量,用于存放 “當(dāng)前狀態(tài)集”,例如:
private int STATUSES;
  • 然后定義十六進(jìn)制狀態(tài)常量,和 “模式狀態(tài)集”,例如:
private final int STATUS_1 = 0x0001;
private final int STATUS_2 = 0x0002;
private final int STATUS_3 = 0x0004;
private final int STATUS_4 = 0x0008;
private final int STATUS_5 = 0x0010;
private final int STATUS_6 = 0x0020;
private final int STATUS_7 = 0x0040;
private final int STATUS_8 = 0x0080;
?
private final int MODE_A = STATUS_1 | STATUS_2 | STATUS_3;
private final int MODE_B = STATUS_1 | STATUS_4 | STATUS_5 | STATUS_6;
private final int MODE_C = STATUS_1 | STATUS_7 | STATUS_8;
  • 當(dāng)需往 “狀態(tài)集” 添加狀態(tài)時(shí),就通過(guò) “或” 運(yùn)算。例如:
STATUSES | STATUS_1
  • 當(dāng)需從 “狀態(tài)集” 移除狀態(tài)時(shí),就通過(guò) “取反” 運(yùn)算。例如:
STATUSES & ~ STATUS_1
  • 當(dāng)需判斷 “狀態(tài)集” 是否包含某狀態(tài)時(shí),就通過(guò) “與” 運(yùn)算。結(jié)果為 0 即代表無(wú),反之有。
public static boolean isStatusEnabled(int statuses, int status) {
   return (statuses & status) != 0;
}
  • 當(dāng)需切換模式時(shí),可直接將預(yù)先定義的 “模式狀態(tài)集” 賦予給 “狀態(tài)集” 變量。例如:
STATUSES = MODE_A;

如此,復(fù)雜度從 m * n 驟減為 m + n,隨著日后模式和狀態(tài)增多,十六進(jìn)制優(yōu)勢(shì)將指數(shù)級(jí)增長(zhǎng)。

是不是超簡(jiǎn)潔?再也無(wú)需定義和修改各種 “setModeXXX” 方法。

而且這還只是一半。另一半是關(guān)于十六進(jìn)制狀態(tài)的存取。

十六進(jìn)制狀態(tài)存取實(shí)戰(zhàn)

由于狀態(tài)集是 int 類型,因而我們最少只需一個(gè)字段,即可存儲(chǔ)狀態(tài)集:

insert into tableXXX TITLE,DATE,STATUS values ('xxx','20190703',32)

讀取也十分簡(jiǎn)單,讀取后直接賦值給 STATUSES 即可。

除此之外,你還可直接在 SQL 中通過(guò)按位計(jì)算來(lái)查詢。例如查詢包含狀態(tài) 0x0004 的記錄:

select * from tableXXX where STATUS & 4 != 0

小結(jié)

未用十六進(jìn)制的日子里,狀態(tài)管理是個(gè)繁瑣、極易出錯(cuò)的操作。

有了十六進(jìn)制后:

  • 模式管理復(fù)雜度從 m * n 驟減至 m + n。
  • 模式切換無(wú)需手動(dòng)清洗,只需為狀態(tài)集變量注入預(yù)置的常量狀態(tài)集。
  • 模式存取一步到位。
  • 模式存儲(chǔ)只需一個(gè)數(shù)據(jù)表字段。
  • 可直接在數(shù)據(jù)庫(kù)中完成查詢狀態(tài)。

作為額外附贈(zèng)的答疑

Q1: 細(xì)心朋友可能注意到,聲明狀態(tài)都是 1、2、4、8,然后進(jìn)一位繼續(xù)。

為何這樣使用?

因?yàn)楫?dāng)十六進(jìn)制轉(zhuǎn)成二進(jìn)制計(jì)算時(shí),十六進(jìn)制每位數(shù)占 4 個(gè)二進(jìn)制位,例如:

0x0001  0x0004    0x0020
   ??      ??        ??
  0001    0100   0010 0000

且唯有獨(dú)占每個(gè)二進(jìn)制位,我們才能區(qū)分出不同狀態(tài)。

因而我們對(duì)十六進(jìn)制數(shù)的每一位只安排 1、2、4、8,一旦用完,就前進(jìn)一位繼續(xù)。

Q2: 既然如此,狀態(tài)聲明為何不直接用二進(jìn)制來(lái)表示?

原因很簡(jiǎn)單 —— 一目了然 0x4218 和密密麻麻 0100001000011000b,在代碼中聲明哪個(gè)更費(fèi)時(shí)、更費(fèi)眼、更易出錯(cuò)? —— 特別是當(dāng)有 20、30 個(gè)狀態(tài)要聲明呢?

以上就是務(wù)必掌握的Android十六進(jìn)制狀態(tài)管理最佳實(shí)踐的詳細(xì)內(nèi)容,更多關(guān)于Android十六進(jìn)制狀態(tài)管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

铜川市| 临洮县| 襄城县| 齐河县| 镇安县| 玛曲县| 西充县| 页游| 黑龙江省| 广饶县| 南岸区| 临沂市| 高唐县| 安仁县| 忻城县| 那曲县| 康平县| 新疆| 镇沅| 苗栗县| 专栏| 宁都县| 天水市| 邯郸县| 衡阳市| 昔阳县| 土默特左旗| 宕昌县| 乐安县| 通榆县| 西乌| 普定县| 万全县| 综艺| 三门县| 汉寿县| 桦川县| 古田县| 绥江县| 舟山市| 若羌县|