Flutter加载JSON资源报错:No such file or directory(errno=2)求助
问题描述
我正在开发一款用于测试自身技能的Flutter应用,但在导入项目中位于assets/repository/translation.json的JSON文件时遇到错误。应用能正常启动,但点击章节查看译文时会出现范围错误,推测是翻译列表为空导致的。
相关代码
TranslationService类
import 'dart:convert'; import 'dart:io'; import 'package:islam_plus/models/translation_model.dart'; import 'package:quran/quran.dart' as quran; class TranslationService { final String _filePath = 'assets/repository/translation.json'; List<AyahTranslation> translationList = []; Future<void> loadTranslations() async { final jsonString = await File(_filePath).readAsString(); print(jsonString); final jsonBody = jsonDecode(jsonString); print(jsonBody); final List<dynamic> quranList = jsonBody['quran']; translationList = quranList .map((dynamic item) => AyahTranslation.fromJson(item)) .toList(); } List<AyahTranslation> getAyahTranslation(int surahNumber) { final totalVerseCount = quran.getVerseCount(surahNumber); int verseCount = 1; final translationFiltered = translationList.where((translation) { if (surahNumber == translation.chapter) { verseCount++; if (verseCount > totalVerseCount) { verseCount = 1; } return true; } return false; }).toList(); return translationFiltered; } String getRandomTranslation(int surahNumber, int verseNumber) { final translationList = getAyahTranslation(surahNumber); final translation = translationList.firstWhere( (translation) => translation.verse == verseNumber, orElse: () => AyahTranslation( chapter: surahNumber, verse: verseNumber, text: 'Translation Not found')); return translation.text; } }
pubspec.yaml配置
flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: assets: - assets/images/number_star.png - assets/repository/translation.json # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware
主页面initState代码
class _QuranPageState extends State<QuranPage> with TickerProviderStateMixin { final service = QuranService(); late TabController _tabController; TranslationService _translationService = TranslationService(); onTabChange(int index) {} @override void initState() { _translationService.loadTranslations(); _tabController = TabController(length: 4, vsync: this); super.initState(); } }
运行错误
E/flutter (10333): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PathNotFoundException: Cannot open file, path = 'assets/repository/translation.json' (OS Error: No such file or directory, errno = 2)
解决方案
1. 替换File读取方式为rootBundle加载assets
Flutter的assets文件是嵌入应用包内的资源,不能直接用File类读取,必须通过rootBundle加载:
修改TranslationService的代码:
import 'dart:convert'; // 移除dart:io的导入 import 'package:flutter/services.dart'; // 新增导入 import 'package:islam_plus/models/translation_model.dart'; import 'package:quran/quran.dart' as quran; class TranslationService { final String _filePath = 'assets/repository/translation.json'; List<AyahTranslation> translationList = []; Future<void> loadTranslations() async { // 用rootBundle加载assets文件 final jsonString = await rootBundle.loadString(_filePath); print(jsonString); final jsonBody = jsonDecode(jsonString); print(jsonBody); final List<dynamic> quranList = jsonBody['quran']; translationList = quranList .map((dynamic item) => AyahTranslation.fromJson(item)) .toList(); } // 其余方法保持不变 }
2. 确认assets文件和路径有效性
- 检查项目中
assets/repository/translation.json是否真实存在,路径大小写需和代码、pubspec.yaml完全一致(Flutter对路径大小写敏感)。 - 执行
flutter pub get确保assets配置生效,必要时重启IDE或热重载应用。
3. 处理异步加载的等待逻辑
当前initState中直接调用异步方法但未等待完成,会导致用户操作时数据还没加载好。可以添加加载状态提示:
修改主页面代码:
class _QuranPageState extends State<QuranPage> with TickerProviderStateMixin { final service = QuranService(); late TabController _tabController; TranslationService _translationService = TranslationService(); bool _isLoading = true; // 新增加载状态标记 onTabChange(int index) {} @override void initState() { super.initState(); _tabController = TabController(length: 4, vsync: this); // 单独封装异步加载方法并更新状态 _loadTranslations(); } Future<void> _loadTranslations() async { await _translationService.loadTranslations(); setState(() { _isLoading = false; }); } @override Widget build(BuildContext context) { if (_isLoading) { return const Center(child: CircularProgressIndicator()); // 加载中提示 } // 原页面的build代码 return ...; } }
内容的提问来源于stack exchange,提问作者Sgt Puke
相关产品推荐
相关产品推荐

