使用 Flutter 开发数字钱包应用(Dompet App)

感谢由 Pixso 资源社区提供的共享作品 《Dompet数字页面设计》

前言

早在几年前,我有幸参与了公司 App 的技术选型,并决定采用 Flutter 技术栈,快速从零搭建出能够集成 H5 应用的 混合应用框架(Hybrid App)。在这个过程中,得益于 Flutter 跨平台特性和高效的 UI 构建能力,我们在短时间内实现了一个功能丰富的混合应用,支持 H5 应用扫码、支付、定位等设备能力。

随着需求的不断迭代与升级,原本的 App 逐渐变得 "臃肿" 起来。回顾当初搭建的 Flutter 混合应用框架,虽然满足了业务上的需求,但在架构设计上显得略为粗糙。面对日益增加的技术负债,依靠业余时间进行优化和重构已然心有余而力不足。是时候重新搭建开发 Flutter 混合应用框架,以便更好的引入最新技术,快速适配各业务场景,提升 App 开发和运行效率。

选型

在构建 Flutter 混合应用 App 的过程中,基于 状态管理依赖注入路由管理国际化(i18n) 等考虑,我们首先选择了 GetX 作为核心框架。随后,为了确保 App 具备 网络请求本地持久化存储本地数据库管理 以及 Webview 等能力,我们进一步引入了 dioget_storagesqfliteflutter_inappwebview 等插件。

然而,开发 App 仅仅依靠 Flutter 技术栈是远远不够的,我们还需要一个具有良好用户体验和精美 UI 界面的设计稿。可惜设计不是我所擅长的领域,好在 Pixso 资源社区提供了丰富的共享作品,在那里我找到了适合我的 UI 设计 《Dompet 数字钱包》

这套设计稿具备以下优点:

  1. 设计精美:界面简洁清晰,用户体验良好,能够给用户带来直观的操作体验。
  2. 便捷登录:设计了 Google、Facebook 第三方登录,免去了繁琐的注册流程。
  3. 功能丰富:包含多种常用组件,具备一定的通用性,便于快速适配不同业务场景。

特性

在技术选型上,我们选择了 GetXdioget_storagesqflite 以及 flutter_inappwebview 作为构建框架的核心基础设施,而在 UI 设计方面,则是选择了 《Dompet 数字钱包》 设计稿作为我们 App 用户界面。

在确定了 Flutter 技术栈、核心插件以及 UI 设计稿后,我们开始着手梳理 Dompet 数字钱包 的 UI 界面和功能需求,以确保高效的开发效率,并成为一个用户体验极佳的 App。

  1. 使用 GetX 中 GetMaterialApp 来接管 App 的路由管理、权限拦截和认证
  2. 使用 GetX 中 .tr,以及自定义 JsonTranslations 实现 App 中英文的切换。
  3. 使用 GetX 中 .obsObx 来取代 GetBuilderupdate 手动更新 UI 的方式
  4. 封装 sqflite 实现本地数据库,存储读取用户、账单、消息、银行卡的数据,模拟服务端处理
  5. 对于 Google 这类第三方登录,我们通过借助 Firebase 平台,实现 Google、Github 便捷登录
  6. 对于 UI 设计稿中的折线图表,我们使用 fl_chart 插件实现,这也是对 Flutter Chart 的首次尝试
  7. 借助 GetX .obsObx 的数据与 UI 更新机制,自定义 extension 单位,自动适配不同设备屏幕
  8. 借助 intl 和 GetX 的 updateLocale 自动处理不同语言和区域格式的数据 (例如 日期不同地区显示)
  9. 借助 image_picker 插件,实现 App 上传来自相册或拍照而的得图片,进而更新用户头像 avatar
  10. 虽然 sqflite 模拟了服务端数据的处理和流转,但网络请求作为 App 基础设施,我们依旧对 dio 进行了封装,完善了 Request 和 Response 拦截处理 (携带 Token、异常处理等)
  11. ......

重要插件依赖如下:

  • 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: (用于状态管理、依赖注入和路由管理,提供简单而高效的开发体验)

源码 - 插件封装

源码 - 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 如下:

github.com/flutter/flu...

演示

https://linpengteng.github.io/resource/dompet-app/app.gif 前往

GitHub

  • Dompet App: https://github.com/DompetApp/Dompet.flutter 前往
  • Webview SDK: https://github.com/DompetApp/Dompet.webview 前往
相关推荐
liangshanbo121521 分钟前
将 Intersection Observer 与自定义 React Hook 结合使用
前端·react.js·前端框架
Python私教22 分钟前
Vue3封装通用确认删除按钮实战案例
前端·javascript·vue.js
林中白虎1 小时前
使用CSS实现酷炫加载
前端·css
资深前端之路1 小时前
vue2 将页面生成pdf下载
前端·vue.js·pdf
什么鬼昵称1 小时前
Pikachu-Cross-Site Scripting-xss之htmlspecialchars
前端·xss
蜡笔小新星1 小时前
在Python中,使用Pillow(PIL的更新分支)库来合并两张图片成一张上下结构的图片
前端·经验分享·python·学习·pillow
黄毛火烧雪下2 小时前
React返回上一个页面,会重新挂载吗
前端·javascript·react.js
浮华似水2 小时前
接口隔离原则在前端的应用
前端
想要打 Acm 的小周同学呀4 小时前
跨域的解决方案
前端·跨域·请求
安冬的码畜日常4 小时前
【D3.js in Action 3 精译_025】3.4 让 D3 数据适应屏幕(中)—— 线性比例尺的用法
前端·javascript·信息可视化·数据可视化·d3.js·d3比例尺·javascript可视化