就算不去火星种土豆,也请务必掌握的 Android 状态管理最佳实践!(1)

直到 2017 年的夏天,我在和一位彼时 3 年经验的同事,联手完成当年扛鼎项目的核心功能时,因同事提出使用十六进制管理状态,而亲眼见证了十六进制在状态管理方面的绝佳优势。

为了纪念同事的这一分享,此后每当有新同事入职,我提供的培训课程必包含十六进制状态管理。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用十六进制前的混沌世界

该项目有个需求:当指定图形编辑的模式时,图形工具栏的按钮状态要随之发生配套性地变化。

例如,存在 3 种图形编辑模式,和 8 个图形编辑按钮。

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

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

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果是传统方式编写,我们势必会在类中为 3 个模式定义 boolean 变量,为 8 个按钮状态定义 boolean 变量。

那么在模式切换时,就需要将每个按钮状态的变量都 “清洗” 一遍。例如:

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() {

}

那要是日后模式变多、按钮状态变多,类中就会满是这种 setMode 的方法,看起来很蠢,而且密密麻麻的 true、false,极容易出错。

这是一点。

另一点就是,如果按钮状态是用 boolean 变量来管理,那么状态的存储和读取怎么办呢?

  • 每个 boolean 变量都要转换成 int 类型的 0 或 1 存储在数据库中。
  • 数据库需要为每个状态准备一个字段。
  • 读取的时候又要负责将每个状态转译回 boolean。

这工作量也太大了!而且日后每添加或修改一个状态,数据库都要新增或修改字段,这非常低效和不安全!

十六进制能很好地解决这些问题

十六进制可以做到:

  • 通过状态集的注入,一行代码即可完成模式的切换。
  • 无论再多的状态,都只需要一个字段来存储。状态被存放在 int 类型的状态集中,可以直接向数据库写入或读取。

十六进制的运作机制

在具体了解十六进制是怎么做到状态管理最佳实践之前,我们先简单过一遍十六进制本身的运作机制。

首先,在编程中,利用开头 0x 表示十六进制数。

例如 0x0001,0x0002。

然后,十六进制的计算,我们可以借助二进制的 “按位计算” 方式来理解。

二进制存在 与、或、异或、取反 等操作:

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

例如,十六进制数 0x0004 | 0x0008,可以理解为:

0100
|
1000

1100

十六进制 (0x0004 | 0x0008) & 0x0004 可以得到:

1100
&
0100

0100

也即状态集中包含某状态时,再与上该状态,就会得到非 0 的结果。

于是,我们就可以利用这个特性来完成状态管理:

十六进制的状态管理实战

  • 首先我们定义一个状态集变量,用来存放当前模式的状态集,例如:

private int STATUSES;

  • 然后我们定义十六进制状态常量,和模式状态集,例如:

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;

  • 当我们需要往状态集中添加状态时,就通过或运算。例如:

STATUSES | STATUS_1

  • 当我们需要从状态集中移除状态时,就通过取反运算。例如:

STATUSES & ~ STATUS_1

  • 当我们需要判断状态集中是否包含某状态时,就通过与运算。结果为 0 即代表无,反之有。

public static boolean isStatusEnabled(int statuses, int status) {
return (statuses & status) != 0;
}

  • 当我们需要切换模式时,我们可以直接将预先定义好的 “模式状态集” 赋予给状态集变量。例如:

STATUSES = MODE_A;

如此,复杂度从 m * n 骤减为 m + n,随着日后模式和状态的增多,十六进制的优势将指数级增长!

是不是超简洁?再也不需要定义和修改各种 “setModeXXX” 方法了。

而且这还只是一半。另一半是关于十六进制状态的存取。

十六进制的状态存取实战

由于状态集是 int 类型,因而我们最少只需一个字段,即可存储状态集:

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

读取也十分简单,读取后直接赋值给 STATUSES 即可。

除此之外,你还可以直接在 SQL 中通过按位计算来查询!例如查询包含状态 0x0004 的记录:

select * from tableXXX where STATUS & 4 != 0

综上

在没有十六进制的日子里,状态管理是个繁琐的、极易出错的操作。

有了十六进制后:

结语

  • 现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。
  • 音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
所以提前做了一些准备。现在拿出来分享给大家。

[外链图片转存中…(img-s5wLNYpY-1715258723027)]

[外链图片转存中…(img-LXLMSnqd-1715258723027)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值