SuperAPI AI 工具集

control-range-must-cover-stored-values

编程与开发

查看项目

更新于 10-17 16:16

技能介绍

用途

该技能用于解决 Kotlin 界面开发中滑块(Slider)控件 valueRange 设置不当的问题。核心观点是:控件的范围不是样式选择,而是对“该控件将接收的所有值都落在范围内”的断言。控件接收值的来源不只是用户手指,还包括导入、恢复、迁移以及自身代码的旧版本。

主要能力

  • 指出范围过窄的典型陷阱:越界值不会被钳制,而是滑块拇指被钳制在边界,读数仍显示真实值,用户看到控件停在极限位置旁边却是一个不等于极限的数字,且不会抛出任何异常。
  • 说明按压拇指会造成无提示的数据丢失:setter 不做钳制,手势驱动才触发 emit;按压拇指会以指针位置对应的原始偏移量调用处理器,由于拇指画在钳制位置,用户按压它得到的是范围端点,处理器将该端点值覆盖越界值。用户打开界面只是想查看设置,离开时却已改变它,且没有任何日志,与故意编辑无法区分。
  • 强调不应参照相邻控件来设定范围:同一区块中两个外观相同的控件可能度量不同的量,例如单个频段的增益与为所有频段让出余量的 trim 计算方式不同,后者合法地比任何单个频段更深。
  • 建议先测量真实分布再确定边界,并把测量依据写入常量注释,例如“六十个已发布配置样本中的最低值为 −12.1 dB”,这样的依据可证伪,能告诉后续维护者边界在什么情况下会出错。
  • 指出非对称范围是合理且常常正确的:用于制造余量的 trim 不应允许提升,否则只会把削波移到别处;不要为了对称而“平衡”范围,范围应跟随值的含义,再放宽以覆盖实际到达的值。
  • 建议若确实需要收窄范围,应在导入阶段钳制并明确告知用户,让导入拒绝或钳制并给出消息,而不是让控件在首次触摸时静默执行。
  • 建议读数舍入方式与控件步进一致:连续范围上按整数舍入的读数会让两个真正不同的状态显示相同数字,用户微调时看不到变化会再次微调;要么给控件离散步进,要么打印足够位数以区分。
  • 指出边界属于存储范围而非控件:任何其他读取该值的组件(第二个后端、导出器、设置摘要)都必须接受相同跨度;在一个构建版本范围下生成的曲线在更窄范围下重新打开,是同一故障从自身旧版本到来。

使用方式

技能提供了验证方法,通过计算真实输入分布的极值并与声明范围比较,而非仅靠推理:

# every declared range in the UI
grep -rn --include='*.kt' 'valueRange' .

# the extremes of what actually arrives — here, the trim line of a sample of profile files.
# LC_ALL=C is load-bearing: under a non-C LC_NUMERIC, `sort -g` orders by the integer part only
# and reports a wrong extreme with no error (-12.1 before -12.9), which is the one thing this
# command exists to get right.
grep -h -i '^Preamp:' sample-profiles/*.txt \
  | sed -E 's/^[Pp]reamp:[[:space:]]*(-?[0-9.]+).*/\1/' \
  | LC_ALL=C sort -g | sed -n '1p;$p'

然后测试两种仅在值来自外部时才会出现的状态:

  • 向存储中植入一个比范围外一步的值,打开界面,断言渲染的数字等于存储的数字——这是捕获“拇指被钉住”的检查;
  • 同样操作后按压拇指,断言存储值没有变成恰好等于范围端点。要断言这一点,而不是“未改变”:在正确范围上,按压任意位置也会发出落点位置的值,因此“未改变”断言会在正确代码上失败。在 −12.1 对 −12f..0f 的情况下按压恰好得到 −12.0;在 −15f..0f 的情况下拇指位于真实位置,发出的值保持在 −12.1 的一个像素内。只做拖拽的测试在两种情况下都会通过,因为拖拽本应改变值。

适用场景

适用于 Kotlin 界面开发中涉及滑块、范围控件、设置项、导入/恢复/迁移数据的场景,尤其是音频处理、配置编辑等需要处理来自外部或旧版本数据的界面。

限制

资料未提供该技能的具体安装命令、依赖要求、支持平台或版本信息,暂未提供。