拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Flutter三方库鸿蒙化适配:numbers_to_text数字转文字与中文金额大写实践

Flutter三方库鸿蒙化适配:numbers_to_text数字转文字与中文金额大写实践

最近在整理一批 Flutter 三方库的鸿蒙化适配,第一个拿到桌面上反复看的就是 numbers_to_text。这个库做的是本地化数值转换:把数字变成人类语言,比如把 1234567 变成“一百二十三万四千五百六十七”。单看功能似乎不大,但一旦落到鸿蒙应用的财务、语音播报、无障碍读屏这些场景,它就成了一个不能含糊的底座。尤其是在国内语境下,合同金额、报销单、发票校验里的中文数字和银行大写,靠手写正则和一堆 if else 很容易翻车,直接用经过验证的转换库会省掉很多心力。

这篇文章不打算只贴一段"复制依赖就能跑"的代码,而是把 numbers_to_text 在鸿蒙工程里从引入到跑通、再到扩展成财务大写能力的过程完整拆一遍。我会尽量讲清楚每一步背后的原因:为什么纯 Dart 库也依然要做适配、鸿蒙端的语言环境怎么拿、金额大写规则为什么不能靠 numbers_to_text 一把梭。如果你正在做 Flutter 鸿蒙迁移,或者只是想在自己的鸿蒙应用里做一套靠谱的中文数字与金额格式化工具,这篇文章应该能给你省下好几天的踩坑时间。

1. 这个库到底解决什么问题,以及为什么值得做适配

1.1 数字转文字,在很多业务里是“刚需”

先不聊鸿蒙,先说数字转文字这个能力本身。人在阅读一串长数字时,比如 158230987,眼睛需要先分组、再逐位辨认,心智负担很大。但如果你把它写成“一亿五千八百二十三万零九百八十七”,哪怕是不太擅长数字的人也能快速建立量级概念。这就是 numbers_to_text 这类本地化数值转换库的核心价值:把机器友好的数字表达转换成人类友好的语言表达。

在很多业务场景里,这个能力根本不是锦上添花,而是硬需求。最典型的是财务场景:合同里的金额大写、报销单的校验、发票打印时金额的“银行大写”,都需要把阿拉伯数字转成中文大写或中文小写。再比如语音播报,如果 App 直接读“余额 12345.67 元”,听感极差,用户一耳朵根本反应不过来是“一万两千三百四十五点六七”还是“十二万三千”。无障碍读屏也有同样的诉求。游戏里的计分、教程里的数学题面、以及儿童教育应用里的数字认知,都需要把数字转成口语化的文本。

numbers_to_text 这个库的优势在于它支持的语言很多,英语、西语、葡萄牙语、法语、德语、意大利语、波兰语、罗马尼亚语、俄语、印地语、中文繁简体都有覆盖。对于要做海外市场又想兼顾国内本地化的团队,一个库能同时覆盖两种业态的转换需求,非常省事。它内部基本是纯 Dart 实现,不依赖 Android 或 iOS 原生代码,这也是我一开始以为“换个工程就能跑”的原因。

1.2 纯 Dart 库不等于零适配

这里必须先把一个误区掰开:纯 Dart 库在鸿蒙上“能编译”和“能像原生端一样稳定工作”是两回事。

纯 Dart 的优点很明显,Dart 运行时在鸿蒙的 Flutter 环境里是完整支持的,所以 numbers_to_text 的核心转换逻辑确实可以直接复用,不需要你用 ArkTS 再写一份。但“引入依赖”只是答案的一半。你要面对的是整个鸿蒙工程链路的变化:Flutter SDK 的分支不同、构建工具是 hvigor 而不是 Gradle、插件加载方式更像“模块集成”而不是“aar/jar 依赖”、原生侧交互要用鸿蒙的 API 能力而不是 Android API。这些链路性的差异,才是鸿蒙化适配的真正工作量。

举一个很具体的例子:numbers_to_text 只是做转换,它本身不需要拿系统参数,但如果我要让它在鸿蒙应用里做到“跟随系统语言自动切换”,我就需要从鸿蒙系统侧读取当前语言偏好,再把这个值传给 Dart 端。读取系统语言这个动作,在 Android 上可以写Locale.getDefault(),在鸿蒙上就得走鸿蒙应用能力框架里的配置接口。这种差异不是 numbers_to_text 造成的,而是平台通道造成的。所以我会把它定义为“库加鸿蒙运行环境的联合适配”,而不是“改造库本身”。

1.3 主要的适配层次

我把这个库的鸿蒙化工作拆成了三个层次,方便理解优先级。

第一层是依赖可用性。确认 numbers_to_text 在鸿蒙 Flutter 工程的 Dart 侧可以被解析、编译、运行,不引入不支持的 FFI 或原生插件。这一层通常半小时内就能搞定。

第二层是能力一致性。同一个输入,在 Android、iOS、鸿蒙三端上要得到完全一致的输出。数字转换这种纯算法逻辑很容易做到,但要注意畸形输入、超大数、负数、小数点的处理行为是否一致。这一层靠测试用例来保证。

第三层是平台差异化能力。比如读取系统语言和国家地区,再比如某些转换场景需要依赖系统货币符号、地区格式。这些能力必须通过鸿蒙的 Platform Channel 来补齐。

理解了这三个层次,后面所有步骤都会变得清晰:先让库跑起来,再补测试,最后处理平台差异。下面我从环境准备开始,逐步讲实操。

2. 适配前准备:把鸿蒙 Flutter 工程和工具链理干净

2.1 鸿蒙 Flutter SDK 怎么选

做鸿蒙 Flutter 适配,第一步不是写代码,而是确认你手上的 Flutter SDK 是支持鸿蒙的版本。OpenHarmony 社区维护了一个针对 HarmonyOS 的 Flutter SDK 分支,和 Google 官方的 Flutter SDK 分支在使用习惯上有差异,比如某些命令的返回信息、插件注册机制、以及内部引擎的 API 都有所不同。

你需要做的第一件事是检查当前环境。我一般先用flutter doctor -v看一遍整体状态,再确认flutter --version。如果输出的版本信息里能看到OpenHarmony或HarmonyOS相关标记,说明分支选对了。如果你是在 DevEco Studio 里直接创建 Flutter 工程,通常它会自动帮你关联到配套的 Flutter SDK,路径在设置里可以查。

这里有一个我踩过的坑:工程里如果同时存在多个 Flutter SDK 路径,很容易导致 Dart 版本不一致,编译时会出现“The current configured Flutter SDK is not known to be fully supported”之类的提示。如果你也碰到这句话,别慌,先检查flutter config里的 SDK 路径是不是指向了鸿蒙分支,尤其要注意不要用官方稳定版去构建鸿蒙工程,否则后面会有一堆莫名其妙的报错。

2.2 pubspec 与依赖解析

SDK 就绪后,就可以把 numbers_to_text 加入到工程依赖里了。在pubspec.yaml中添加:

dependencies: flutter: sdk: flutter numbers_to_text: ^3.2.0

然后执行flutter pub get。这一步如果顺利,说明这个库的 Dart 侧依赖没有踩雷。

不过 pub get 成功只代表“能拉到包”,不代表“能编译”。我建议你顺手做一次依赖树检查:

flutter pub deps --style=compact

重点看 numbers_to_text 有没有传递性依赖。它本身很干净,一般不会有问题。但如果你后续在同一个工程里接了其他数值处理库,就要小心intl这类包,因为intl的版本可能和 Flutter SDK 内置的版本冲突。如果真的冲突,优先选择把依赖版本抬高到和目标 SDK 兼容的版本,而不是强行覆盖 pubspec 约束。

另外一个容易被忽略的问题是flutter_test的依赖。如果你在鸿蒙环境下跑单元测试,pubspec 里的dev_dependencies中flutter_test版本必须和 SDK 匹配。在 OpenHarmony 分支下,有些版本的flutter_test不能直接在桌面环境里跑,需要调整成“忽略测试”或改在鸿蒙设备上跑。这个细节我会在后面的测试部分再展开。

2.3 构建工具链:从 Gradle 到 hvigor

适配到这个阶段,你会发现鸿蒙工程与原生的 Flutter 工程在底层构建上完全换了套路。Android 工程依赖 Gradle,而鸿蒙工程依赖 hvigor,构建脚本和任务名都不一样。这意味着你在 Android 上的一句./gradlew assembleRelease,在鸿蒙这里要换成hvigorw配合 HAP 打包命令。

如果你是在 DevEco Studio 里打开鸿蒙 Flutter 工程,IDE 一般会帮你把 hvigor 相关的东西配好。但我建议至少要手动跑一次命令行构建,因为 CI 环境大概率用得上。先找到工程根目录下的hvigorw,然后执行:

./hvigorw assembleHap

首次构建会特别慢,因为要下载鸿蒙 SDK 的公共依赖,还会编译 Flutter 引擎相关的加载库。耐心等即可,如果出现签名相关报错,说明设备调试用的证书没有配置,需要先到AppScope/app.json5里确认signingConfigs是否完整。

构建工具链的坑大多集中在环境变量上。鸿蒙 SDK 的路径、Flutter SDK 的路径、Node 版本,任何一个不对都会报错。我建议在工作目录下建一个local.properties文件,把sdk.dir显式写出来,这样可以避免 IDE 和命令行读到不一致的配置。

3. 核心实现:让数字表达在鸿蒙上“语言级直观”

3.1 理解 numbers_to_text 的语言规则

在动手之前,至少要弄明白这个库的基本调用方式。以中文为例,大概是这样:

import 'package:numbers_to_text/numbers_to_text.dart'; final converter = NumbersToText(language: Language.ZHT); final result = converter.toText(1234567); // 结果大致为:一百二十三万四千五百六十七

不同版本的 API 名称可能有差异,比如toText可能叫convert,或者要传NumberToTextRequest。我这里强调的是思路,不是让你照搬方法名,真到你本机上,打开包源码看一眼接口定义就知道怎么调了。

这个库处理中文的方法值得夸一句:它对“零”的规则处理得比较细致。比如 10001 会转成“一万零一”,而不是“一万零零一”;10010 会转成“一万零一十”。这些细节看起来简单,但你手动写规则时很容易出错,尤其是连续多个零的情况。语言规则引擎的价值就在这,它把零处理、单位分级、负数符号、小数点读法都封装好了。

中文里还有繁简体之分。Language.ZHT是繁体中文,Language.ZHH是简体中文。如果你面向大陆市场,要用ZHH。如果面向港澳台,再考虑ZHT。这个选择不要写死,最佳实践是跟随系统语言动态决定。

3.2 解决“语言环境从哪来”的问题

要让转换行为跟随系统设置,Dart 侧就得知道设备当前是什么语言。虽然 Flutter 框架本身也提供PlatformDispatcher.instance.locale这类 API,但在鸿蒙分支上,这个值不一定能反映用户后来在系统设置里切换的语言,因为底层的实现和 Android 不完全一致。

我的做法是在鸿蒙侧主动拿一次系统语言,通过 MethodChannel 发给 Dart 端。这样既不依赖 Flutter 框架内部对鸿蒙的适配完整度,也能保证拿到的值一定来自系统层,后续切换语言时只需要重新拉取一次。

Dart 侧定义一个通道:

import 'package:flutter/services.dart'; class LocaleBridge { static const MethodChannel _channel = MethodChannel( 'com.example.numeric_formatter/locale', ); static Future<String> getSystemLanguage() async { try { final result = await _channel.invokeMethod<String>('getSystemLanguage'); return result ?? 'zh_Hans'; } on PlatformException catch (_) { return 'zh_Hans'; } } }

鸿蒙原生侧用 ArkTS 注册这个 Handler,返回系统当前语言。不同版本的鸿蒙 SDK 获取语言的方式不太一样,你现在看到的是通过getCapability或资源管理接口来拿,具体 API 以你本机的 SDK 为准。只要保证返回值的格式统一成语言_地区风格就行,比如zh_CN。

知道系统语言后,再决定用ZHH还是ZHT,这样基本能做到“系统切语言,数字表达跟着变”。

3.3 财务场景扩展:从“数字转文字”到“金额大写”

numbers_to_text 的定位就是通用数字转文字,它不会帮你输出“壹佰贰拾叁万肆仟伍佰陆拾柒元整”这种银行大写。国内财务场景真正缺的其实是这个能力,这也是我在标题里把“财务治理底座”单独拎出来的原因。

那怎么在不重写轮子的前提下实现金额大写?我的思路是用 numbers_to_text 做整数部分的转换基础,自己再补一套“人民币大写规则”。这类规则并不复杂,核心就是两步:第一步把数字拆成整数部分和小数部分;第二步把整数部分映射到“壹贰叁肆伍陆柒捌玖”,单位映射到“拾佰仟万亿”,小数部分映射到“角分”。

这里有个和通用数字转换不同的点:银行大写里数字要全部替换为大写汉字,而 numbers_to_text 默认给的是普通汉字。所以我并不建议直接拿 numbers_to_text 的输出做字符串替换,因为通用表达里“零”的出现规则和银行大写里“零”的出现规则有细微差别。更稳妥的做法是你写一个专门的大写转换函数,把整数拆解逻辑自己处理,用类似下面的模式:

String toRmbUpper(num amount) { final intPart = amount.floor(); final decimalPart = ((amount - intPart) * 100).round(); // 这里实现“亿/万/仟/佰/拾”逐级拆解与“零”的合并规则 // 返回类似:壹佰贰拾叁万肆仟伍佰陆拾柒元捌角玖分 }

你可能会问:那 numbers_to_text 在这里还有什么用?它仍然有价值,因为在很多业务里,系统展示文案用的是“一百二十三万四千五百六十七元”,而不是银行大写。一个是给人读的,一个是给财务凭证用的。两个输出可以并存:日常展示走 numbers_to_text,财务专用走大写规则。这样既省了重复造轮子,又保证了专业场景的合规表达。

3.4 适配中要关注的 Unicode 与文本格式

很多人会在数字转文字后直接拼字符串展示,结果遇到换行、对齐、标点符号不统一的问题。鸿蒙的文本渲染引擎对 Unicode 的支持总体没问题,但你要注意几个细节。

第一个是中文标点。转换结果里的逗号、句号、小数点要统一用全角还是半角,这取决于你的展示容器和阅读场景。财务报告里多用全角中文标点,代码日志里反而建议半角,避免日志系统解析出错。

第二个是负号和括号。财务场景里负数金额经常写成“(壹佰贰拾叁)”而不是“负壹佰贰拾叁”,这种表达习惯不能靠库解决,得在你自己的格式化层处理。我会在调用层做一层适配:金额小于零时,先取绝对值转换,再根据业务需求决定是加“负”字还是加括号。

第三个是超大数和精度。Dart 的num类型在处理超过一定位数的大数时,小数部分可能会有浮点误差。如果你要转换的金额涉及分位精确计算,我建议在业务层先把单位换成“分”存储,也就是用整数去算,最后再转成元展示。这是金融系统的通行做法,也能避免一堆精度问题。

4. 实操记录:把 numbers_to_text 落地到鸿蒙工程

4.1 建立工程结构

我的落地路径不是新建一个鸿蒙工程,而是在已有的 Flutter 鸿蒙工程里加模块。如果你是从零开始,建议先通过 DevEco Studio 创建一个带 Flutter 模块的鸿蒙工程,然后保持目录结构清晰,至少要有这几个部分:dart侧代码放业务逻辑,ohos目录放鸿蒙原生入口与平台通道,test目录放转换测试。

下面是简化过的目录示意:

my_harmony_app/ ├── ohos/ │ ├── entry/ │ │ ├── src/main/ets/ │ │ │ ├── entryability/ │ │ │ └── pages/ │ └── build-profile.json5 ├── lib/ │ ├── main.dart │ └── services/ │ └── number_locale_bridge.dart ├── test/ │ └── numbers_conversion_test.dart ├── pubspec.yaml └── hvigorw

我特意把lib/services单独建目录,因为后面你很可能不止一个平台通道,把通道逻辑收敛到一个目录里,维护成本会低很多。原生侧的 EntryAbility 只负责注册,不做具体业务,这也是一个值得坚持的规范。

4.2 原生侧注册 MethodChannel

鸿蒙原生侧注册 Handler 时,我的做法是在EntryAbility的初始化流程里挂载。代码如下,依然以你本机 SDK 的 API 为准:

import { MethodChannel } from '@ohos/flutter_ohos'; function registerNumberChannels() { const channel = new MethodChannel('com.example.numeric_formatter/locale'); channel.setMethodCallHandler((call) => { if (call.method === 'getSystemLanguage') { const lang = getSystemLanguageFromConfig(); return Promise.resolve(lang); } return Promise.reject('unsupported method'); }); }

注册时间尽量靠前,最好在 Flutter 页面加载完成前完成,否则 Dart 侧第一次调用时可能拿不到响应,白白触发异常分支。

同时,我在同一套结构里预留了第二个通道,用来返回当前地区使用的货币代码。因为某些场景下你可能需要显示“CNY”“USD”这样的币种符号,单纯靠系统语言推断货币不一定准。这个通道的编码思路和语言通道一致,无非就是改为调用货币相关接口。

4.3 编写本地化转换服务类

原生侧通道建好后,Dart 侧就可以提供一个统一的服务类,把语言获取、转换、财务大写封装在一起,业务页面尽量不直接依赖 numbers_to_text 的 API。这样将来如果你想把转换库换成自研实现,只改服务类,不用动页面代码。

一个简化版本的服务类大概是这样的:

class NumberLocalizationService { Future<String> toText(num value) async { final lang = await LocaleBridge.getSystemLanguage(); final language = lang.startsWith('zh') ? Language.ZHH : Language.ENGLISH; final converter = NumbersToText(language: language); return converter.toText(value); } Future<String> toRmbUpper(num value) async { // 调用自研人民币大写逻辑 } }

实际开发里我还会加一个缓存层,把语言参数缓存起来,避免每次调用数字转换都去走一遍原生通道。因为通道调用虽然快,但在高频场景下也算不必要的开销。缓存可以做成:App 启动时取一次,系统切换语言时通过通知刷新,业务侧每天基本都是同一个语言环境,没必要频繁拉取。

测试的时候我建议覆盖这些边界:0、负数、带小数的金额、万位和亿位的交界处、连续零的数字。尤其是连续零的用例,建议把 1001、10001、100001、10000001 这几个值都测一遍。你会发现很多转换库在这些值的处理上差距很大,踩过坑的人自然懂。

4.4 打包 HAP 与真机验证

本地调试阶段通过后,就要打包成 HAP 上真机验证了。鸿蒙的构建和 Flutter 的flutter build不是同一条命令,你需要通过 hvigor 构建出 HAP 包,然后在 DevEco Studio 里跑签名与安装。

打包时有一个容易忽略的点:Flutter 资源的打包。如果你在pubspec.yaml里声明了 assets,鸿蒙端的构建脚本要把这些 assets 一并打进 HAP,有时候还会要求你在ohos模块的module.json5里配置资源目录。否则你会发现本地 IDE 运行一切正常,但打包之后某些图片或语言配置文件找不到。

签名问题也是高频报错点。鸿蒙应用安装到真机上需要签名,调试签名和发布签名是两套体系。我建议趁早配置好自动签名,不然每台设备都要手动导入证书,团队协作时特别耽误事。

打包验证时,我还会随手检查日志里有没有 Flutter 引擎相关的 warning。很多问题在 debug 模式下不出现,release 模式下才会冒出来,这类问题通常和引擎裁剪有关,比如 release 包去掉了部分 UTF 相关的文本处理能力,导致某些字符显示异常。真机 HDMI 投屏看一遍展示效果,比在 IDE 里看截图更靠谱。

5. 常见问题与排查思路

5.1 错误码 2300056 这类运行时错误怎么定位

在鸿蒙开发群里经常有人发类似“Android 请求正常,鸿蒙请求返回 2300056”的帖子。这个错误码出现在网络请求相关的场景里比较多,含义对应网络不可用或访问受限。需要注意的是,这类错误有时候并不是网络真的不可用,而是缺少权限声明,或者域名没加到网络安全配置里。

虽然 2300056 跟 numbers_to_text 本身没有直接关系,但如果你把一个带网络请求的鸿蒙应用和数字转换功能一起做联调,非常容易被这个错误打断节奏。我的建议是先把它当作“环境错误”而不是“代码错误”来查:第一步看module.json5里面有没有声明网络权限;第二步确认请求地址是否支持 HTTPS;第三步看是不是设备本身连了受限网络。大部分情况都是这三板斧能解决。

5.2 数字转换结果在 Release 包中不一致

我遇到过一种情况:同一个数字,在 Debug 包转换正常,在 Release 包里变成了奇怪的符号。排查到最后发现是 Flutter 引擎的 release 模式做了 tree shaking,某些字符映射表没有被完整打进包里。这个问题和鸿蒙适配没有绝对关系,在 Android 上也可能出现,只是鸿蒙的打包链路更需要你手动确认。

遇到这种问题,优先做两件事:第一,升级到 OpenHarmony 社区当前推荐的稳定版 Flutter SDK,很多字符缺失问题是早期分支的 bug;第二,添加一个“预启动自检”,在 App 启动时内置一段固定数字转换测试,如果结果和预期不符,直接上报日志。这比用户反馈“显示乱码”再排查要高效得多。

5.3 中文数字处理的边界条件

用 numbers_to_text 时要特别留意超大数。虽然 Dart 的num能存储很大的整数,但中文数字表达里“亿”以上还有“兆”“京”等更大的单位,不同库的支持程度不一样。如果你的业务金额很少超过万亿级,基本不用担心。但做数据大屏、政务报表这类项目,建议先确认库在 10^12 以上量级的表现,不够再自己补。

另一个边界是“零”。中文数字表达式里零的出现非常有讲究,10010 是“一万零一十”而不是“一万零十”,1000010001 是“十亿零一万零一”,这些规则手动维护起来很头疼。numbers_to_text 在这点上做得够用,但你在测试时一定要把这些连续零用例铺进去,防止未来升级库版本时行为变化。

小数部分也同样需要测试。1.5 转成中文应该是“一点五”而不是“一点五零”,2.05 应该是“二点零五”而不是“二点五”。如果库的旧版本处理不到位,建议做一层后处理,把末尾多余的零去掉。

5.4 问题排查速查表

为了方便查阅,我把上面提到的问题整理成一张表:

现象可能原因排查顺序
pub get 报依赖冲突传递依赖与 Flutter SDK 版本不匹配检查依赖树,调整版本约束,锁定直接依赖
构建报 SDK 不支持的提示Flutter SDK 选了非鸿蒙分支重新配置 SDK 路径,确认分支版本
真机安装失败签名配置或证书未正确导入检查签名配置,重新生成调试证书
数字转换结果在 Release 和 Debug 不一致引擎字符映射表被裁剪升级引擎版本,做启动自检
系统语言切换后转换语言未变缓存未刷新或通道未重新调用监听系统语言变更,刷新缓存
HAP 包内资源找不到assets 未配置到鸿蒙模块检查 module.json5 资源配置
网络请求返回 2300056权限缺失或网络环境限制排查权限声明、HTTPS、设备网络

这张表不止适用于 numbers_to_text,很多 Flutter 库迁移到鸿蒙时都会遇到类似的问题。本质都是同一件事:Dart 层逻辑容易迁移,平台层的接口、配置、构建链路需要逐项对齐。

6. 我在适配中总结的经验

用 numbers_to_text 做鸿蒙化适配这件事,技术上并不复杂,真正花时间的反而是那些“预期之外”的部分。我最大的体会是:纯 Dart 库的鸿蒙化不是“把库塞进工程”这么简单,你在 Android 上没注意过的系统语言获取、资源打包、Release 引擎裁剪,到了鸿蒙环境里都会重新冒出来。尤其在一个 App 同时维护 Android 和鸿蒙双端时,哪怕转换逻辑一模一样,两端的验证路径也不能互相替代。

测试用例是我最想强调的一点。数字转换这类功能,边界值一旦有 bug,业务方在正式环境很容易发现,而且影响往往很严重。我会在工程里保留一组固定的回归用例,包含 0、负数、小数、万亿级、连续零、繁简体切换,每次升级依赖、切换引擎或者调整构建配置后都跑一遍。这个习惯帮我挡掉过至少两次升级库版本带来的回归。

如果你是在做财务相关 App,建议不要把 numbers_to_text 的输出直接作为银行大写凭证,那套规则必须独立实现并单独测试。数字转文字解决的是“人能顺利读懂”,金额大写解决的是“财务合规”,两者目标不同,我强烈建议不要让一个函数同时承担两种职责。

后面如果你要继续扩展,可以考虑把转换能力做成一个独立的本地化服务模块:英文数字、中文数字、银行大写、货币格式化统一收口,再给鸿蒙端补上系统语言监听。这样不仅 numbers_to_text 能用,未来接入其他格式化库,也只需要替换服务内部实现,对外接口完全不受影响。这大概就是鸿蒙化适配里最值得投入的那部分。

返回列表