就算不去火星种土豆,也请务必掌握的 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

综上

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

有了十六进制后:

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值