Flutter如何不重启应用读取更新后的本地JSON文件而非旧缓存数据
问题根因
rootBundle仅用于读取应用编译时打包进安装包的静态资源,这类资源运行时无法被修改,不管你往什么位置写同名文件,调用rootBundle.loadString()永远只会返回安装包内固化的初始版本数据,这是不重启应用读不到新内容的核心原因。- 你写入文件时使用的
File('jsonfile/primary_values.json')是相对路径,没有指向应用专属的可读写沙盒目录,实际写入的文件位置和你后续读取的位置完全不匹配。 - 写入操作完成后没有主动触发文件重读与UI刷新逻辑,就算文件写入成功,界面也不会自动同步最新值。
修复方案
1. 统一文件读写路径
应用运行时产生的修改必须存储在系统分配的应用专属沙盒目录中,你需要先将初始打包的JSON文件在首次启动时拷贝到沙盒目录,后续所有读写操作都针对沙盒内的这份文件,不再直接操作rootBundle中的静态资源。
首先实现获取沙盒内目标文件的通用方法:
import 'package:path_provider/path_provider.dart'; import 'dart:convert'; import 'dart:io'; Future<File> _getLocalJsonFile() async { // 获取应用可读写的专属文档目录 final appDocDir = await getApplicationDocumentsDirectory(); return File('${appDocDir.path}/primary_values.json'); }
实现文件初始化逻辑,首次启动时拷贝静态资源到沙盒:
Future<void> _initJsonConfig() async { final configFile = await _getLocalJsonFile(); // 沙盒中不存在配置文件时,从静态资源拷贝初始版本 if (!await configFile.exists()) { final initialContent = await rootBundle.loadString('jsonfile/primary_values.json'); await configFile.writeAsString(initialContent); } // 初始化完成后读取最新内容渲染 await readJson(); }
2. 改造读文件逻辑
将原来从rootBundle读数据的逻辑,改为直接读取沙盒内的配置文件:
Future<void> readJson() async { try { final configFile = await _getLocalJsonFile(); final String fileContent = await configFile.readAsString(); final data = jsonDecode(fileContent); final values = PrimaryValueJson.fromJson(data); setState(() { if (primaryKey == 'Doctor SSN :') { widget.primaryIndex = values.doc_ssn; widget.primaryValue = 'DC0${widget.primaryIndex}'; print(widget.primaryValue); print('this is readjson'); } }); } catch (e) { print("读取配置失败: $e"); } }
替换initState中的初始化调用:
@override void initState() { super.initState(); print("I am doctor init screen"); // 替换原来的readJson()调用 _initJsonConfig(); }
3. 改造写文件逻辑,写完主动刷新
写入时同样操作沙盒文件,写入完成后主动触发重读,确保UI同步最新值:
Future<void> _writeJson() async { try { final configFile = await _getLocalJsonFile(); // 读取沙盒中最新的配置内容,不要读rootBundle final String fileContent = await configFile.readAsString(); final data = jsonDecode(fileContent); final values = PrimaryValueJson.fromJson(data); final PrimaryValueJson updatedConfig = PrimaryValueJson( doc_ssn: values.doc_ssn + 1, phar_id: values.phar_id, ssn: values.ssn, ); // 写入更新后的配置 await configFile.writeAsString(json.encode(updatedConfig.toJson())); print('this is writejson:${updatedConfig.doc_ssn}'); // 清空输入框 nameController.text = ''; specialityController.text = ''; experienceController.text = ''; widget.primaryIndex = updatedConfig.doc_ssn; widget.primaryValue = 'DC0${updatedConfig.doc_ssn}'; // 重读文件刷新UI await readJson(); } catch (e) { print("写入配置失败: $e"); } }
4. 修复异步调用问题
你原来在insertRecord方法中把异步的_writeJson包在setState里没有等待执行完成,会出现时序问题,将对应代码修改为:
// 移除原来包裹_writeJson的setState await _writeJson(); setState(() {});
注意:如果之前运行过旧版本代码,建议先卸载应用重装,确保旧的错误路径缓存文件被清理,首次启动会自动完成初始配置拷贝。
内容的提问来源于stack exchange,提问作者Samman Shrestha
相关产品推荐
相关产品推荐

