Flutter应用版本更新时如何指定部分assets资源替换/不替换规则?
实现方案
核心逻辑前提
Flutter的assets目录是安装包内置的只读目录,用户无法直接修改该路径下的文件,每次应用更新时整个assets目录都会被新版本的内置文件完全覆盖。你要保留用户修改的settings.json,本质上是你在应用首次启动时,已经把assets下的这两个文件复制到了应用的可读写目录(如应用文档目录、支持目录),后续读写操作都是针对可读写目录下的副本进行的。
所以只需要调整文件复制的判断逻辑即可实现需求:
具体实现步骤
- 第一步:添加路径依赖,在
pubspec.yaml中添加相关依赖,用来获取可读写目录路径、拼接路径
dependencies: flutter: sdk: flutter path_provider: ^2.1.0 path: ^1.8.3
同时记得配置assets资源引用:
flutter: assets: - assets/database.db - assets/settings.json
- 第二步:应用启动时执行文件复制逻辑,核心判断规则如下:
- 先获取可读写目录的路径,分别拼接得到两个文件在可读写目录下的目标路径
- 对于
database.db:每次启动都直接用assets里的新版本文件覆盖可读写目录下的旧副本即可 - 对于
settings.json:只有当可读写目录下不存在该文件时(一般是用户首次安装应用),才从assets复制初始文件,只要文件已经存在就跳过复制,自然保留用户的原有修改
- 第三步:示例代码
import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; Future<void> initAssetsFiles() async { // 获取应用支持目录(用户不可见,不会被误删) final supportDir = await getApplicationSupportDirectory(); // 处理database.db:每次都用内置新版本覆盖 const dbAssetPath = 'assets/database.db'; final dbTargetPath = path.join(supportDir.path, 'database.db'); final dbBytes = await rootBundle.load(dbAssetPath); await File(dbTargetPath).writeAsBytes( dbBytes.buffer.asUint8List(), mode: FileMode.writeOnly, ); // 处理settings.json:仅不存在时复制初始文件 const settingsAssetPath = 'assets/settings.json'; final settingsTargetPath = path.join(supportDir.path, 'settings.json'); final settingsFile = File(settingsTargetPath); if (!await settingsFile.exists()) { final settingsBytes = await rootBundle.load(settingsAssetPath); await settingsFile.writeAsBytes(settingsBytes.buffer.asUint8List()); } }
- 第四步:后续所有对这两个文件的读写操作,都直接操作可读写目录下的目标路径文件即可,不要直接读取assets下的原文件。
注意事项
如果后续你需要给settings.json新增默认配置项,不要用覆盖文件的方式实现,而是在读取配置的时候,把读取到的用户配置和代码里的默认配置做合并,给缺失的字段补默认值即可,不会改动用户已有的配置内容。
内容的提问来源于stack exchange,提问作者Tanzilo
相关产品推荐
相关产品推荐

