自从 HarmonyOS 的适配需求摆在面前,我第一反应是:一个纯 Dart 的条码解析库,理论上在哪个 Flutter 环境都能跑,鸿蒙怎么会例外?结果第一次编译就直接把我手里这套药品追溯扫码应用给撂那儿了。做医药流通的客户要求 App 同时支持鸿蒙,而整个应用最核心的数据解析逻辑几乎全压在 gs1_barcode_parser 这个三方库上——从 GS1 标准条码串里拆出 GTIN 商品编码、批次号、有效期这些关键字段,解析不出来,后面所有业务逻辑都白搭。
这篇文章我不打算只讲“怎么把这个库编译通过”,因为那样太浅了。我会把整个适配过程完整记录下来:gs1_barcode_parser 的内部原理、鸿蒙化之前需要做的评估、我在中间层引入“物联大桥”做数据桥接的完整设计、具体改了什么代码、踩了哪些坑,以及一套以后你做任何 Flutter 三方库鸿蒙化都能直接套用的排查方法。适合正在做鸿蒙适配的 Flutter 开发、搞扫码/IoT 方向的技术负责人,以及想深入理解条码解析原理的同学。
1. 项目背景与方案选型:为什么是 gs1_barcode_parser
1.1 gs1_barcode_parser 到底解决了什么问题
先说清楚一件事:扫码枪或者手机扫码 SDK 扫完 GS1 条码,拿到的往往只是一串看似没有规律的数字和字母,比如 01069012345678921723010110LOT20250311。这串东西如果没有解析规则去拆,根本没法直接落库。
GS1 标准条码的核心思想是“AI 应用标识符 + 数据段”。开头的 01 表示后面跟的是 GTIN 全球贸易项目代码,17 表示有效期,10 表示批次号。问题是这些 AI 里,有的是固定长度,比如 01 固定接 14 位数字;有的是可变长度,比如 10 批次号最长 20 位,完全靠分隔符来截断。你要是自己写正则去匹配,光把这些规则列全就够写几百行,更别提 GS1-128、GS1-Databar、GS1-QR 的症状还各不相同。
gs1_barcode_parser 这个库就是干这个的。它把 GS1 规范里的 AI 字典和解析规则全部封装好,开发者只需要调用一个 parse 方法,传入原始条码串,就能拿到结构化的结果。比如传入 01069012345678921723010110LOT20250311,它能明确告诉你 GTIN=06901234567892、有效期=23年01月01日、批次号=LOT20250311。
没有这个解析层,扫码应用只能做最笨的整串匹配,业务系统稍微改个条码格式,App 端就要跟着改,这在药品追溯这种强监管场景里是不可接受的。所以我接到鸿蒙化需求后的第一个任务很清晰:让这个库在鸿蒙的 Flutter 环境里正确跑起来,同时保证解析结果和 Android/iOS 完全一致。
1.2 鸿蒙化之前的三个自我拷问
拿到任务后我没有立刻开干,而是先列了几个问题,把这次适配的真实工作量估清楚。
第一问:这个库有没有依赖平台相关的能力?我翻了 gs1_barcode_parser 的源码和 pubspec.yaml,确认它的核心解析逻辑全部在 Dart 层完成,不涉及 dart:io 的文件操作,不涉及 MethodChannel 的原生调用,连 Flutter 的 binding 都没碰。这意味着它属于“纯 Dart 包”,理论上在任何支持 Dart 运行时的环境都能编译。
第二问:既然是纯 Dart 包,为什么第一版编译还是失败了?后来查下来问题出在 Flutter 鸿蒙运行时本身。鸿蒙的 Flutter 环境不是 Google 原版,而是社区和厂商维护的分支,Dart 版本、运行时能力、依赖解析策略都有差异。gs1_barcode_parser 里用到的某些集合操作或者正则特性,在鸿蒙分支的 Dart SDK 上行为不一致,直接导致编译期或者运行期报错。
第三问:就算编译过了,怎么保证解析结果和原版一致?这正是这次适配里最容易被忽略的部分。很多团队移植第三方库只看“能不能编译通过”,忽略了功能等价性。GS1 条码的解析规则非常严谨,年度、有效期这些字段一旦错位,导致药品批次追溯出问题,是要出严重事故的。
这第三问直接决定了我后面的方案:不能“改完能跑”就收工,必须有一个可衡量的验证方案。也正是在这份验证方案的设计过程中,我决定引入“物联大桥”这个中间层。
1.3 方案选型:用“物联大桥”做数据桥接,而不是硬改解析器
一开始有两条路摆在面前。第一条最省事:直接把 gs1_barcode_parser 扔进鸿蒙工程,能编译就编译,编译不过就改源码。第二条稍微麻烦一点:搞一个桥接层,把扫码采集、数据归一化、条码解析三个环节解耦,解析器只是其中一个可以被替换的组件。
我选了第二条,因为这个“物联大桥”中间层对鸿蒙化来说几乎是必需的结构。原因很简单:手机扫码 App 这条链路里,条码解析只是末端环节。条码从哪来?在 Android 上是 CameraX 扫码,在鸿蒙上是通过系统扫一扫 Kit 或者鸿蒙原生扫码 API。这俩返回的原始条码串、退化格式、甚至字符编码都可能不同,如果解析器直接跟扫码 SDK 绑死,每次换扫码实现都要动解析层。
“物联大桥”组件就是做这个解耦的。上层业务只跟中间层通信,中间层负责统一调用各平台的扫码能力,拿到条码后调 gs1_barcode_parser 做语义解析,尽可能把平台差异挡在解析器外面。这样一来,真正需要针对鸿蒙做适配的,就只剩扫码数据采集这一小段,解析器本身保持“纯净”。
事实也证明这个决定是对的。整个鸿蒙化过程中,gs1_barcode_parser 的 Dart 代码我只改了一行 import 路径,其他所有适配工作都发生在桥接层和构建配置。省了大力气,还保留了后续替换解析器的自由度。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心机制拆解:gs1_barcode_parser 怎样工作
2.1 GS1 条码体系核心:AI 应用标识符
要理解这个库,必须先理解 GS1 条码体系里的 AI 应用标识符。打个比方:GS1 条码就像一份结构化的表格,AI 是表格里的列名,跟在 AI 后面的数据是单元格内容。01 是“国际商品编码”这一列,17 是“有效期”这一列,10 是“批次号”这一列。
不同 AI 的取值格式差别很大,我整理了一份高频使用的 AI 清单:
| AI 标识 | 含义 | 数据格式 | 长度类型 |
|---|---|---|---|
| 01 | GTIN 全球贸易项目代码 | 14 位数字 | 固定长度 |
| 10 | 批次号 | 最长 20 位字母数字 | 可变长度 |
| 11 | 生产日期 | YYMMDD,6 位数字 | 固定长度 |
| 17 | 有效期 | YYMMDD,6 位数字 | 固定长度 |
| 21 | 序列号 | 最长 20 位字母数字 | 可变长度 |
| 310n | 净重(kg) | 6 位数字,n 表示小数位数 | 固定长度 |
| 37n | 数量 | 最长 8 位数字 | 可变长度 |
注意上表的 310n,这里的 n 不是字母,而是一个数字占位符,表示后面 6 位数值里小数点向左移几位。如果是 3103,后面接 000250,那么实际净重是 0.250kg。这类细节最容易在解析阶段出错,也最能体现解析器存在的价值。
可变长度 AI 的处理则更难一些。比如 10 批次号最长 20 位,但当它后面还有其他 AI 数据段时,必须用 FNC1 分隔符来告诉解析器“批次号到这里结束”。扫码设备解码之后,这个分隔符通常会变成一个不可见或者特殊的控制字符。gs1_barcode_parser 需要在解析时识别这个字符,并且不能把它当作正式数据塞进字段值里。这个逻辑如果实现不严谨,出现的 Bug 会非常隐蔽——字段错位,但条码看起来却“解析成功了”。
2.2 解析器内部实现主线:扫描、提取、校验、再扫描
我翻了下 gs1_barcode_parser 的源码结构,它的核心流程其实是一条主循环,大致可以拆成四步。
第一步,从输入字符串的开头开始,尝试识别前 2 到 4 位字符是否为已知的 AI 标识。GS1 规范里 AI 最短 2 位,最长 4 位,解析器需要根据已有字典做最长匹配,避免把 01 开头的 GTIN 错认成其他 AI。
第二步,根据匹配到的 AI 元数据,判断后续数据长度。如果是固定长度 AI,直接按位截取。如果是可变长度 AI,则需要向后扫描到 FNC1 分隔符,或者到整个字符串的末尾。
第三步,对截取出的数据做格式校验。比如 GTIN 的 14 位数字最后一位是校验位,需要按模 10 算法验证;日期字段要检查月份和日期是否在有效范围内。校验失败时,解析器通常会扔出异常或者在结果里标记错误。
第四步,把已解析的 AI 和数据段保存到结果集,然后移动解析游标到剩余串的头部,重复前面三步,直到整串数据全部消费完毕。
这个库在实现上主要靠一个 AI 规则字典 + 若干正则,把解析逻辑收敛得很薄。这也意味着只要字典正确、正则的边界情况覆盖完整,解析逻辑本身在跨平台时不需要太多改动。
看一段简化的核心逻辑,便于理解:
dart复制List<GS1Element> parse(String barcode) {
final elements = <GS1Element>[];
var cursor = 0;
while (cursor < barcode.length) {
final ai = _matchAI(barcode, cursor);
if (ai == null) {
throw GS1ParseException('Unknown AI at position $cursor');
}
final rawValue = switch (ai.lengthType) {
AILengthType.fixed => barcode.substring(cursor + ai.code.length, cursor + ai.code.length + ai.length),
AILengthType.variable => _readUntilSeparator(barcode, cursor + ai.code.length),
};
final element = GS1Element(ai.code, rawValue);
_validate(element);
elements.add(element);
cursor += ai.code.length + rawValue.length;
}
return elements;
}
这段代码做了极大的简化,真实实现里还要处理 FNC1 分隔符、跳过空数据段、处理 AI 嵌套规则等。但主线就是扫描、提取、校验、再扫描,理解这条主线之后,你在鸿蒙上排查解析问题会从容很多。
2.3 鸿蒙化真正要动的地方:不是解析器,而是周围环境
我把这次鸿蒙化的适配点列了个清单,看完你会惊讶于解析器本身几乎没动,精力全花在周边环境上。
第一块是依赖和构建。鸿蒙的 Flutter 工程虽然在 pubspec.yaml 里声明依赖的方式不变,但真正拉取和编译时,用的是鸿蒙分支的 Flutter SDK 和对应的构建工具链。这里出现过依赖解析失败、锁文件版本冲突的问题,具体我会在第四章展开。
第二块是 dart:io 及平台能力。如果你引入的库直接引用了 dart:io 或者 Flutter 的 platform channel,鸿蒙支持情况得单独验证。gs1_barcode_parser 不涉及,所以这块直接跳过。
第三块是扫码数据入口。Android 上从摄像头拿到的一帧画面,经过 MLKit 或者 ZXing 解码得到条码字符串;鸿蒙上调用系统扫码能力的方式完全不同。这部分差异必须由“物联大桥”桥接层消化,不能让解析器关心条码是从哪个平台拿到的。
第四块是验证方案。鸿蒙端没有现成的“跑一遍全部用例”的 CI 环境,需要手动搭一套可重复的回归测试。我后面会把测试用例怎么设计、条码样本库怎么建、以及怎么对比解析结果是否与 Android 端一致讲清楚。
所以你看,当有人问“这个库鸿蒙化难度大不大”的时候,我的标准回答是:解析器本身不大,难的是你永远不知道它背后还有多少东西依赖平台差异。鸿蒙化从来不是改一个库,而是改一整条链路。
3. 实操:把 gs1_barcode_parser 跑在鸿蒙上的全过程
3.1 环境准备:DevEco Studio 与 Flutter 鸿蒙 SDK
这次实操使用的环境组合如下,你可以作为参考。但注意,Flutter 鸿蒙化的生态变化极快,版本组合以你们项目引进时的最新稳定版为准,别一味照抄。
我用的组合是:Flutter 3.22 的鸿蒙分支 + OpenHarmony SDK API 12 + DevEco Studio 5.0 及以上版本。准备阶段最麻烦的是要同时维护两套构建体系。一套是 Flutter 自己的 Dart 构建,负责把 Dart 代码编译成原生产物;另一套是鸿蒙的 hvigor 构建,负责把 Flutter 产物打包成鸿蒙应用。两条链路必须对齐,任何一条版本跳了,另外一条很可能就跟着编译失败。
创建一个支持鸿蒙的 Flutter 工程,大致流程是先用 Flutter 官方命令创建普通工程,再用 DevEco Studio 打开工程里的 harmony 目录做鸿蒙原生配置。如果你项目的 pubspec.yaml 里已经声明了 gs1_barcode_parser 依赖,Flutter 侧不需要额外配置,鸿蒙工程构建时会自动通过 pub 拉取依赖。
这一步我最想提醒你的是:千万别跳过 flutter pub get 之后的锁文件检查。鸿蒙分支的 Flutter SDK 跟官方 SDK 的依赖解析策略偶发不一致,锁文件如果是从 Android 工程复制的,鸿蒙侧首次构建很容易因为依赖版本解析失败而中断。
3.2 集成 gs1_barcode_parser:第一轮就翻车
在 pubspec.yaml 里加依赖没有任何悬念,真正翻车的是加完依赖之后的编译阶段。我在 dependencies 下加了这行:
yaml复制dependencies:
gs1_barcode_parser: ^1.2.0
然后在 Dart 代码里很自然地写:
dart复制import 'package:gs1_barcode_parser/gs1_barcode_parser.dart';
final parser = GS1BarcodeParser();
final result = parser.parse('01069012345678921723010110LOT20250311');
执行 flutter build hap 构建鸿蒙包,编译过程直接在解析器内部某处抛出了一个类型转换异常。报错信息没有明确指向是哪一行代码,只提示 Dart SDK 的 RegExp 匹配行为差异。这种问题最磨人,因为它不是语法错误,不是缺依赖,纯粹是运行时行为不一致。
排查手段是去 gs1_barcode_parser 的源码里搜索所有正则表达式,然后逐个在鸿蒙 SDK 的 Dart 环境里跑一遍用例。最终定位到一个对 GS1-128 分隔符的匹配正则,在鸿蒙分支的 Dart 正则引擎上,对某些 Unicode 控制字符的匹配结果和官方 Dart SDK 不一致。
我的处理方式很保守:不改 gs1_barcode_parser 的任何解析逻辑,只在工程里加了一个小的补丁包,通过依赖覆盖的方式修正那一个正则表达式。因为解析规则是行业标准和公共契约,随便改库源码,后面升级版本会非常痛苦;用依赖覆盖做局部修正,升级时只要重新评估补丁是否还需要,成本低得多。
这里也补一句:如果你用的版本已经修复了这类问题,你大概率不会走到这一步,但我建议你也验证一遍,不要假设它是好的。
3.3 实现“物联大桥”桥接层:Dart 到鸿蒙的握手
环境问题解决之后,就要解决扫码数据来源的问题。我在 Dart 侧定义了一个统一的扫码服务接口,这就是“物联大桥”在代码层面的形态。先看抽象部分:
dart复制abstract class BarcodeSource {
Future<String?> scanBarcode();
}
class HarmonyBarcodeSource extends BarcodeSource {
static const MethodChannel _channel = MethodChannel('com.iotbridge/barcode');
@override
Future<String?> scanBarcode() async {
final String? raw = await _channel.invokeMethod<String>('scan');
return raw;
}
}
然后在业务层,通过“物联大桥”统一入口把扫码结果交给解析器,Android 端和鸿蒙端使用同一套解析代码:
dart复制class BarcodeService {
BarcodeService({required BarcodeSource source, required GS1BarcodeParser parser});
Future<ParseResult> process() async {
final raw = await source.scanBarcode();
if (raw == null) return ParseResult.failure('scan timeout');
return ParseResult.success(parser.parse(raw));
}
}
鸿蒙侧的实现,需要在鸿蒙工程的 ArkTS 组件里注册同一个 MethodChannel 的方法处理器,调用鸿蒙系统扫码能力,拿到结果后通过通道回调到 Dart 层。核心逻辑大概长这样:
typescript复制import { MethodChannel } from 'flutter_sdk';
const channel = new MethodChannel('com.iotbridge/barcode');
channel.setMethodCallHandler(async (call) => {
if (call.method === 'scan') {
const result = await scanByHarmonyKit();
return result;
}
});
这里的 scanByHarmonyKit 是封装鸿蒙扫一扫 Kit 的调用,需要你根据项目实际使用的 API 编写。我强调一下:Dart 侧和鸿蒙侧的通道名称必须完全一致,数据格式我用的是字符串直传,没有做 Base64 编码,因为条码内容本身就是文本协议,不存在二进制数据穿透的问题。如果你要传图片或者视频帧,就得考虑字节流的跨平台序列化方案了。
“物联大桥”这一层的价值在联调阶段体现得最明显:Android 端和鸿蒙端跑的是同一份 BarcodeService 代码,只在应用启动时注入不同的 BarcodeSource,所以我只需要在鸿蒙适配初期重点盯扫码入口,后面所有业务迭代都能两边同步推进。
3.4 测试用例设计与验证方案
集成完成不等于移植完成。为了验证解析结果和 Android 端完全一致,我建了一套测试条码样本库,覆盖了三类场景。一是 GS1-128 条码,重点覆盖固定和可变长度 AI 混合;二是 GS1-Databar 条码,用来验证分隔符处理;三是 GS1-QR 码,用来验证带 FNC1 的复杂场景。
每条样本都维护了期望解析结果,然后分别在 Android 端 Flutter 环境和鸿蒙端 Flutter 环境跑同一套测试代码对比输出。为了自动化,我写了一个对比脚本,从 JSON 文件里读取样本库和期望结果,两端各自生成解析结果 JSON,再做逐字段比对。脚本本身不复杂,关键在用例覆盖度,我至少准备了 60 多条用例。
抽样看几条代表性用例:
dart复制final cases = <String, String>{
// GTIN + 有效期 + 批次号,固定/可变长度混合
'01069012345678921723010110LOT20250311': '01:06901234567892|17:230101|10:LOT20250311',
// 带 FNC1 分隔符的可变长度 AI,后面还跟着 GTIN
'10LOT2025031D0106901234567892': '10:LOT202503|01:06901234567892',
// 3103 净重,带 3 位小数
'01069012345678923103000250': '01:06901234567892|3103:000250',
// 生产日期 + 序列号,序列号有字母
'1125010112ABC123XYZ': '11:250101|21:ABC123XYZ',
};
最终两端输出一致性达到百分之百,才算真正完成了这次鸿蒙化适配。
4. 踩坑记录与问题排查
4.1 问题速查表:高频坑一网打尽
这次实战中遇到的技术问题不少,我把高价值的整理成了一张速查表,方便你以后直接查:
| 现象 | 根因 | 解决方式 |
|---|---|---|
| 鸿蒙侧首次编译失败,提示 Dart 正则行为不一致 | 鸿蒙分支 Dart SDK 正则引擎对控制字符匹配有差异 | 用依赖覆盖打局部补丁,不修改库源码 |
| 扫码结果为空字符串 | ArkTS 侧 MethodChannel 注册时机晚于 Dart 侧调用 | 在鸿蒙页面生命周期 onLoad 阶段提前注册通道 |
| 可变长度 AI 后面的字段被吞掉 | FNC1 分隔符没有被正确识别 | 在桥接层对扫码返回的原始串做一次归一化,把控制字符转成统一标识 |
| 解析 GTIN 校验位时偶发异常 | 部分测试条码本身校验位错误 | 解析器校验失败时抛出异常,需要业务层自行决定是否接受弱校验 |
| 构建锁文件冲突 | 从 Android 工程复制 pubspec.lock 导致 | 删除锁文件,在鸿蒙工程里重新 pub get |
这张表看着简洁,但每一条背后都有一段痛苦排查,下面我挑几个典型场景展开讲讲。
4.2 解析结果错位的真实案例:FNC1 分隔符引发的“惨案”
有一回联调时,测试同事拿了一组真实药品包装上的条码来扫,解析出的批次号总是多出一截,把后面紧跟的 GTIN 前几位吞掉了。我拿到原始条码串一看,中间有个不可见控制字符,正是 FNC1 分隔符在解码后的表现。
问题在于,不同扫码设备对这个分隔符的输出不一样。有的设备输出 ASCII 码 0x1D,有的设备直接把它过滤掉了,还有的设备输出成普通的百分号字符 %。gs1_barcode_parser 只认其中一种,拿到别的形式就识别不了,于是把分隔符当成了数据内容,往后多吃了几个字符。
这个坑的排查思路是:在“物联大桥”桥接层做一次输入归一化,把各种表现形式的 FNC1 分隔符统一成一个内部标识,再喂给解析器。这样无论前端用什么扫码设备、鸿蒙 SDK 返回什么格式,解析器永远拿到的是它最熟悉的形式。
另外提醒一句:千万不要在解析器外层做字符串 replaceAll 了事,因为有的条码内容里可能真的含有百分号字符,盲目替换会污染正式数据。正确做法是只在固定位置识别控制字符,而不是全局替换。
4.3 日期字段的格式理解错误:YYMMDD 不是你以为的年月日
GS1 里的生产日期 11 和有效期 17 都是 YYMMDD 格式,这个 YY 只有两位,而且规范里有自己的世纪映射逻辑。最初我们团队的业务同事直接把这个 YY 当成“年份后两位”,在界面上拼接成 2023、2026 之类的完整年份,平时看着没问题,但遇到 00 到 69 和 70 到 99 跨越世纪的时候就会出歧义。
gs1_barcode_parser 本身返回的日期数据是原始字符串,不做世纪推测,这是合理的设计。但业务层如果不了解 GSM 规范的世纪规则,就很容易踩坑。这次适配时我在“物联大桥”的数据字典里加了一个日期标准化字段,专门把 YYMMDD 转换成 ISO 8601 格式传给上层,把世纪歧义风险统一消化掉。
这是个典型的“库没做错,但业务层理解错”的案例。所以我建议所有做条码解析的团队,在接口文档里明确标注原始字段和标准字段,不要偷懒只传一个字符串。
4.4 性能与稳定性实测
解析器性能这块,我在真机上跑了一轮测试。选取 1 万条混合类型的 GS1 条码样本,循环解析十轮,统计耗时的结果大致如下:
| 测试项 | 耗时(毫秒) |
|---|---|
| 单条条码平均解析耗时 | 0.03 ms |
| 1 万条解析耗时 | 约 300 ms |
| 10 万条解析全程 GC 次数 | 不超过 5 次 |
| 常驻内存增量 | 小于 5 MB |
单条不到 0.05 毫秒的解析速度,对扫码业务来说完全不是瓶颈。真正影响体验的环节在扫码解码那一层——摄像头对焦、图像识别、条码定位,这些才是耗电耗时的大头。所以鸿蒙化调优的重心应该放在扫码采集环节,而不是解析器。
内存方面,gs1_barcode_parser 在解析完成后会释放大部分临时对象,长驻内存非常稳定,没有出现内存泄漏问题。我把结果跟 Android 端跑出的数据做了对比,差异在误差范围内。这也是纯 Dart 库移植到鸿蒙的一个优势:只要运行时能力对齐,性能表现基本一致。
5. 经验总结与后续扩展思路
5.1 鸿蒙化三方库的通用方法论
经过这次实战,我把 Flutter 三方库的鸿蒙化流程总结成了四步判断法,任何库拿到手上都能用这套思路走一遍。
第一步,给库做体检。看 pubspec.yaml,看源码里有没有 dart:io、package:flutter/services.dart、package:ffi 这类平台相关依赖。纯 Dart 库直接跳到第三步,依赖平台能力的库进入第二步。
第二步,梳理平台的接口映射。把库对 Android/iOS 原生能力的调用列一个清单,然后逐个在鸿蒙侧找对应的替代实现。这个阶段最容易发现能力断层,比如某个 Android API 在鸿蒙上根本没有等价函数,需要你自己造轮子。
第三步,构建适配与补丁管理。永远不要直接改三方库源码,优先用依赖覆盖、运行时补丁等手段做局部修正,并记录修改点和原因,方便升级时复盘。
第四步,建立端到端验证方案。准备一套覆盖核心业务的测试用例,Android 端作为参照基准,在鸿蒙端跑同一套数据,逐字段比对输出。这一步不做,前面都是白干。
5.2 后续还能怎么扩展
“物联大桥”这套桥接层跑通之后,我其实已经拿它复用了好几个场景。一个是把解析结果直接投递给上游 MES 系统,另一个是接入了更多扫码硬件设备,比如鸿蒙办公平板的摄像头扫码,不需要改动上层业务。
如果你想继续往深处扩展,有几个方向可以看看。一是扩充 gs1_barcode_parser 的 AI 字典,覆盖更多行业自定义 AI,比如医疗领域的有效期校验扩展;二是把“物联大桥”模块化,做成独立的鸿蒙 Flutter 插件发布出去,其他项目直接引用;三是结合鸿蒙的分布式能力,把条码解析服务抽象成跨设备能力,手机扫码,平板实时同步结果。
就我个人体验来说,这次鸿蒙化最有价值的产出不是把某个库跑通了,而是逼迫我重新梳理了一遍扫码链路里到底哪些是平台相关的、哪些是业务相关的。以前在 Android 上不会认真想的问题,换一个运行时环境全暴露出来了。以后无论鸿蒙生态怎么演进,这套拆解思路都不会过时。
