Flutter:await执行后跳转新页面出现卡顿问题求助
Hey there, let's figure out why your new page is stuttering right after scanning a barcode. I've run into similar issues before, so here are the most common fixes to try:
1. Offload Navigation to Avoid Main Thread Blocking
The BarcodeScanner.scan() call might be holding up the main thread while it processes the scan result. When you immediately call Navigator.pushNamed() right after, it's trying to run navigation animation on a thread that's still busy cleaning up from the scan.
Quick Fix: Use Post-Frame Callback
Wrap your navigation code in a post-frame callback to ensure it runs only after the current UI frame is fully completed:
Future scan() async { try { String barcode = await BarcodeScanner.scan(); // Let the current frame finish before triggering navigation WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).pushNamed('/restaurant_menu_screen_2'); }); } catch (e) { print('Scan error: $e'); // Handle errors (e.g., user canceled scan) } }
Alternatively, you can use Future.delayed(Duration.zero) which does a similar thing by pushing the navigation to the end of the event loop:
Future.delayed(Duration.zero, () { Navigator.of(context).pushNamed('/restaurant_menu_screen_2'); });
2. Optimize the Target Page's Initialization
If the lag is coming from the new page itself (not the navigation), it's likely that RestaurantMenuScreen2 is doing heavy synchronous work in initState() or during build (like parsing large datasets, rendering complex UI immediately).
Fixes for the Target Page:
Move Heavy Work to Async Functions:
Don't block the build process with data loading or parsing. Use an async function ininitState()and update the UI withsetState()once done:class RestaurantMenuScreen2 extends StatefulWidget { @override _RestaurantMenuScreen2State createState() => _RestaurantMenuScreen2State(); } class _RestaurantMenuScreen2State extends State<RestaurantMenuScreen2> { List<MenuItem>? _menuItems; bool _isLoading = true; @override void initState() { super.initState(); _loadMenuData(); // Start loading data asynchronously } Future<void> _loadMenuData() async { // Replace with your actual data fetch/parsing logic final rawData = await fetchMenuFromApi(); final parsedItems = parseMenuItems(rawData); // Heavy parsing here setState(() { _menuItems = parsedItems; _isLoading = false; }); } @override Widget build(BuildContext context) { if (_isLoading) { return Center(child: CircularProgressIndicator()); // Show loading state } // Render your menu UI once data is ready return ListView.builder( itemCount: _menuItems?.length ?? 0, itemBuilder: (context, index) => ListTile(title: Text(_menuItems![index].name)), ); } }Use Isolates for Extreme Workloads:
If your parsing or data processing is extremely heavy (like thousands of menu items), offload it to an Isolate to keep the main thread free for UI:import 'dart:isolate'; Future<void> _loadMenuData() async { final receivePort = ReceivePort(); await Isolate.spawn(_parseMenuInIsolate, receivePort.sendPort); final parsedItems = await receivePort.first as List<MenuItem>; setState(() { _menuItems = parsedItems; _isLoading = false; }); } void _parseMenuInIsolate(SendPort sendPort) { // This runs in a separate thread, no main thread block final rawData = fetchMenuFromApiSync(); // Sync call is okay here final parsedItems = parseMenuItems(rawData); sendPort.send(parsedItems); }
3. Check for Library-Specific Issues
The barcode_scan library is a bit outdated—consider switching to a more modern, maintained package like mobile_scanner which has better performance and less main thread blocking. It's a drop-in replacement for most use cases and might resolve the lag entirely.
内容的提问来源于stack exchange,提问作者user8934578

