感谢由 Pixso 资源社区提供的共享作品 《Dompet数字页面设计》
前言
早在几年前,我有幸参与了公司 App 的技术选型,并决定采用 Flutter 技术栈,快速从零搭建出能够集成 H5 应用的 混合应用框架(Hybrid App)。在这个过程中,得益于 Flutter 跨平台特性和高效的 UI 构建能力,我们在短时间内实现了一个功能丰富的混合应用,支持 H5 应用扫码、支付、定位等设备能力。
随着需求的不断迭代与升级,原本的 App 逐渐变得 "臃肿" 起来。回顾当初搭建的 Flutter 混合应用框架,虽然满足了业务上的需求,但在架构设计上显得略为粗糙。面对日益增加的技术负债,依靠业余时间进行优化和重构已然心有余而力不足。是时候重新搭建开发 Flutter 混合应用框架,以便更好的引入最新技术,快速适配各业务场景,提升 App 开发和运行效率。
选型
在构建 Flutter 混合应用 App 的过程中,基于 状态管理 、依赖注入 、路由管理 和 国际化(i18n) 等考虑,我们首先选择了 GetX 作为核心框架。随后,为了确保 App 具备 网络请求 、本地持久化存储 、本地数据库管理 以及 Webview 等能力,我们进一步引入了 dio
、get_storage
、sqflite
和 flutter_inappwebview
等插件。
然而,开发 App 仅仅依靠 Flutter 技术栈是远远不够的,我们还需要一个具有良好用户体验和精美 UI 界面的设计稿。可惜设计不是我所擅长的领域,好在 Pixso 资源社区提供了丰富的共享作品,在那里我找到了适合我的 UI 设计 《Dompet 数字钱包》
这套设计稿具备以下优点:
- 设计精美:界面简洁清晰,用户体验良好,能够给用户带来直观的操作体验。
- 便捷登录:设计了 Google、Facebook 第三方登录,免去了繁琐的注册流程。
- 功能丰富:包含多种常用组件,具备一定的通用性,便于快速适配不同业务场景。
特性
在技术选型上,我们选择了 GetX
、dio
、get_storage
、sqflite
以及 flutter_inappwebview
作为构建框架的核心基础设施,而在 UI 设计方面,则是选择了 《Dompet 数字钱包》 设计稿作为我们 App 用户界面。
在确定了 Flutter 技术栈、核心插件以及 UI 设计稿后,我们开始着手梳理 Dompet 数字钱包 的 UI 界面和功能需求,以确保高效的开发效率,并成为一个用户体验极佳的 App。
- 使用 GetX 中
GetMaterialApp
来接管 App 的路由管理、权限拦截和认证 - 使用 GetX 中
.tr
,以及自定义JsonTranslations
实现 App 中英文的切换。 - 使用 GetX 中
.obs
和Obx
来取代GetBuilder
与update
手动更新 UI 的方式 - 封装 sqflite 实现本地数据库,存储读取用户、账单、消息、银行卡的数据,模拟服务端处理
- 对于 Google 这类第三方登录,我们通过借助 Firebase 平台,实现 Google、Github 便捷登录
- 对于 UI 设计稿中的折线图表,我们使用 fl_chart 插件实现,这也是对 Flutter Chart 的首次尝试
- 借助 GetX
.obs
与Obx
的数据与 UI 更新机制,自定义 extension 单位,自动适配不同设备屏幕 - 借助 intl 和 GetX 的
updateLocale
自动处理不同语言和区域格式的数据 (例如 日期不同地区显示) - 借助 image_picker 插件,实现 App 上传来自相册或拍照而的得图片,进而更新用户头像 avatar
- 虽然 sqflite 模拟了服务端数据的处理和流转,但网络请求作为 App 基础设施,我们依旧对
dio
进行了封装,完善了 Request 和 Response 拦截处理 (携带 Token、异常处理等) - ......
重要插件依赖如下:
flutter_ringtone_player:
(系统提示音,用于转账、支付、充值成功时的系统提示)flutter_inappwebview:
(App Webview, 用于访问 H5 Web 应用)google_sign_in:
(Google 账号免密登录,用于实现便捷的用户身份验证)firebase_core:
(Firebase 的核心依赖,为其他 Firebase 服务提供基础支持)firebase_auth:
(Firebase 平台认证,支持多种认证方式,目前用到了 Google 和 GitHub)path_provider:
(获取应用的常用存储路径,例如:临时目录、文档目录)fluttertoast:
(用于在应用中显示短暂的消息提示,支持error、warnning、 success)image_picker:
(用于选择和拍摄图片或视频,方便用户上传和处理媒体文件)get_storage:
(轻量级的本地存储解决方案,用于存储简单数据,如用户登录状态)fl_chart:
(用于绘制各类图表,如折线图、柱状图等,方便可视化数据展示)sqflite:
(Flutter 的 SQLite 插件,用于在本地存储和管理结构化数据)intl:
(国际化和本地化支持库,帮助处理不同语言和区域格式的数据)dio:
(强大的 HTTP 客户端,支持各种请求方式、拦截器和响应处理,适用于网络请求)get:
(用于状态管理、依赖注入和路由管理,提供简单而高效的开发体验)
源码 - 插件封装
- lib/configure/dio: 封装了 Request 和 Response 拦截处理 (携带 Token、异常处理等)
- lib/configure/sqflite: 封装定义 Sqfliter 为 App 创建、打开、关闭、删除 sqlite,提供便捷的 Api
- lib/configure/fluttertoast: 封装定义了通用的 Toaster,支持 error、warning、success 三种消息体
- lib/configure/get_translate: 借助 GetX 定义 JsonTranslations, 解析 JSON 数据格式的多语言国际化
- lib/configure/image_picker: 封装定义 MediaPicker 便于 App 从用户设备的相册中选择图片或视频
- lib/configure/path_provider: 封装定义 PathProvider 为 App 提供了便捷的 Api 来访问这些系统目录
源码 - Extension 扩展
- lib/extension/date: 为不同语言和地区提供日期本地化格式方案 (eg. US: Oct 4, 2024)
- lib/extension/bool: 为 Dart 所有类型转换 bool 类型,提供了便捷方案 (eg. 'string'.bv => true)
- lib/extension/money: 定义提供了金额显示的多种方式 USD、usd2 (eg. 1000.usd2 => '$1,000.00')
- lib/extension/size: 适配不同设备的屏幕以及屏幕翻转时自适应,定义多种单位 (wdp、wmax、sr ...)
源码 - 全局应用服务
- lib/service/event: 定义了全局的事件。例如 登录、退出、更新用户信息,创建订单、创建消息等
- lib/service/locale: 定义存储了全局的 locale、以及语言国际化处理。如切换中英文、使用系统语言
- lib/service/media: 定义储存了 mediaQuery 状态,借助
.obs
实现 UI 自动更新 (如 设备翻转时) - lib/service/native: 定义创建了 Flutter Dart 与 原生 IOS、Android 端 的 MethodChannel 消息通道
- lib/service/sqlite: 定义创建了 App 本地数据库(sqlite),并为不同的用户账号分配各自数据库资源
- lib/service/store: 定义维护了全局数据存储 (例如 用户、订单、银行卡...),并自动同步 UI 更新
- lib/service/webview: 定义创建了 Flutter 与 Webview 端的 WebviewChannel,类似 JS Bridge
遗憾
在开发过程中,虽然我们通过 Flutter 技术栈和丰富的插件实现了许多功能,但仍遇到了一些不尽如人意的地方,特别是在集成 国内支付 (微信支付、支付宝) 上。国内支付必须通过企业或第三方服务商,且得有资质情况下,才能完成支付认证和集成,对个人开发者并不太友好。
此外,这次 数字钱包应用 的开发,主要目的是为了探索和搭建 Flutter App 框架 ,并没有计划将其上架。因此,我们暂时没有进行 App 订阅 功能的集成和测试,这也算是项目中的一个小遗憾。对于 App 订阅 的实现与集成,没有实际的开发经验。如果有熟悉这方面的朋友,欢迎在评论区留言分享,感谢!
注意
如果你对 数字钱包应用 感兴趣,想从 Github 下载下来,运行在自己的设备上。需要注意的是,无论是账号密码的登录注册,还是 Google 或 Github 的便捷登录,因为使用了 Firebase 平台的认证,在国内你可能需要 VPN,否则 数字钱包应用 可能会因网络问题而卡死。
有关这个问题的 issues 如下:
演示
https://linpengteng.github.io/resource/dompet-app/app.gif
前往