如何在Flutter中同步(无需await)读取Assets文件夹中的文件
Ah, I get it—you're trying to read Flutter assets synchronously because your code flow works better with blocking calls, but the File approach isn't working. Let's break down why that's happening and how to fix it.
Why File.readAsStringSync() Fails
Flutter packages assets directly into your app's bundle, not as separate files on the device's filesystem. When you use File('./assets/...'), you're trying to access a path that doesn't exist in the device's native file system—hence the "No such file or directory" error.
1. The Recommended Approach: Preload Assets Asynchronously (Avoid Blocking)
Even though you want synchronous access, the best practice in Flutter is to load assets once at app startup, cache them, and then use the cached values synchronously everywhere else. This avoids blocking the UI thread (which causes jank or app freezes).
First, double-check your pubspec.yaml is correctly configured to include the assets (this step is easy to miss!):
flutter: assets: - assets/ble_db/characteristic_uuids.json - assets/ble_db/service_uuids.json # Or use the folder shorthand if you have multiple files: # - assets/ble_db/
Then preload the assets before launching your app:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; List? _charList; List? _servicesList; Future<void> main() async { // Critical: Initialize Flutter binding before calling async methods in main WidgetsFlutterBinding.ensureInitialized(); // Load assets once at startup await _preloadAssets(); runApp(const MyApp()); } Future<void> _preloadAssets() async { final charString = await rootBundle.loadString('assets/ble_db/characteristic_uuids.json'); _charList = jsonDecode(charString); final serviceString = await rootBundle.loadString('assets/ble_db/service_uuids.json'); _servicesList = jsonDecode(serviceString); } // Now you can use the cached values in any synchronous function void mySyncFunction() { if (_servicesList != null) { print('Loaded services: ${_servicesList!.length}'); } }
2. If You Must Have Synchronous Blocking Code (Not Recommended)
If you absolutely need to read assets synchronously (e.g., for legacy code or non-UI thread logic), you can use Isolate.run (available in Dart 2.19+) to run the async asset load in a separate isolate and wait for the result synchronously. This avoids blocking the main UI thread if used carefully.
Example:
import 'dart:convert'; import 'dart:isolate'; import 'package:flutter/services.dart'; List? _charList; List? _servicesList; void loadAssetsSynchronously() { // Run async asset load in an isolate and wait for the result final charJson = Isolate.run(() => rootBundle.loadString('assets/ble_db/characteristic_uuids.json')); _charList = jsonDecode(charJson); final serviceJson = Isolate.run(() => rootBundle.loadString('assets/ble_db/service_uuids.json')); _servicesList = jsonDecode(serviceJson); }
⚠️ Warning: Calling this on the main UI thread will block it, causing your app to freeze until the assets load. Only use this in background isolates or non-critical code paths.
内容的提问来源于stack exchange,提问作者Oleksii

