Flutter页面间数据传递问题:如何同步设置页与首页数据
Flutter页面间数据传递:设置页单位同步到首页
我知道这类问题有很多相关提问,但我是Flutter新手,还没找到契合自身需求的方案,可能我的思路有偏差。在Flutter开发中,几乎每个页面都需要向其他页面传递数据,也可能需要从其他页面接收返回的数据。
以下是我的相关代码:
home.dart
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'applicationbar.dart'; import 'navigationdrawer.dart'; import 'bluetooth.dart'; class Home extends StatefulWidget { @override _HomeState createState() => _HomeState(); } class _HomeState extends State<Home> { String _string = '0m'; //若settings.dart中_isFeetChecked为true,则此处显示'0ft' @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[900], appBar: ApplicationBar(title: 'Luggage Follower'), drawer: NavigationDrawer(), body:Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0), child: Text('good Status', style: Theme.of(context).textTheme.body2), ), Padding( padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0), child: Text('Paired', style: Theme.of(context).textTheme.body1), ), Padding( padding: const EdgeInsets.symmetric(vertical: 20,horizontal: 0), child: Divider(height: 3.0, color: Colors.pinkAccent, indent: 150, endIndent: 150), ), Padding( padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0), child: Text('Distance to Luggage', style: Theme.of(context).textTheme.body2), ), Padding( padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0), child: Text(_string, style: Theme.of(context).textTheme.body1), //动态文本 ), Padding( padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0), child: LuggageFollow(), ), ], ), ); } }
settings.dart
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:audioplayers/audio_cache.dart'; import 'applicationbar.dart'; import 'navigationdrawer.dart'; class SettingsData { bool feet; bool metres; SettingsData({this.feet, this.metres}); } class Settings extends StatefulWidget { @override _SettingsState createState() => _SettingsState(); } class _SettingsState extends State<Settings> { static bool _isFeetChecked = false; static bool _isMetersChecked = true; @override Widget build(BuildContext context) { return Scaffold( appBar: ApplicationBar(title: 'Settings'), drawer: NavigationDrawer(), body: Column( //crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Padding( padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 20), child: Text('Distance Units') ), Divider( height: 3.0, color: Colors.pink, ), Padding( padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 0), child: CheckboxListTile( title: Text('Distance in feet', style: Theme.of(context).textTheme.body1), value: _isFeetChecked, onChanged: (bool value) { setState(() { _isFeetChecked = value; _isMetersChecked = !value;}); }, checkColor: Colors.white, activeColor: Colors.pink, subtitle: Text('1 foot ~ 0.3 metres',style: Theme.of(context).textTheme.display2), ), ), Padding( padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 0), child: CheckboxListTile( title: Text('Distance in metres', style: Theme.of(context).textTheme.body1), value: _isMetersChecked, onChanged: (bool value) { setState(() { _isMetersChecked = value; _isFeetChecked = !value;updateData();}); }, checkColor: Colors.white, activeColor: Colors.pink, subtitle: Text('1 metre ~ 3 feet',style: Theme.of(context).textTheme.display2), ), ), Padding( padding: EdgeInsets.symmetric(vertical: 30.0,horizontal: 20), child: Text('Notifications') ), Divider( height: 3.0, color: Colors.pink, ), ), ), ], ), ); } }
我需要实现设置页的单位选择同步到首页的显示,请问该如何实现Flutter页面间的数据传递?
解决方案
针对你的需求,这里提供三种适合新手的实现方式,从简单到进阶:
方法一:使用Navigator返回数据(临时传递,不持久化)
这种方法适合从设置页返回首页时同步数据,不需要依赖第三方库。
修改步骤:
修改Settings页面,添加返回数据逻辑
去掉静态变量(静态变量不适合组件间状态管理),在用户选择单位后通过Navigator.pop返回数据:class _SettingsState extends State<Settings> { bool _isFeetChecked = false; bool _isMetersChecked = true; // 返回数据给首页 void _navigateBack() { Navigator.pop(context, SettingsData(feet: _isFeetChecked, metres: _isMetersChecked)); } @override Widget build(BuildContext context) { return Scaffold( appBar: ApplicationBar( title: 'Settings', leading: IconButton( icon: Icon(Icons.arrow_back), onPressed: _navigateBack, ), ), body: Column( children: [ // ... 其他代码 CheckboxListTile( title: Text('Distance in feet', style: Theme.of(context).textTheme.body1), value: _isFeetChecked, onChanged: (bool? value) { setState(() { _isFeetChecked = value ?? false; _isMetersChecked = !_isFeetChecked; }); _navigateBack(); // 选择后立即返回同步 }, // ... 其他属性不变 ), // 另一个Checkbox同理修改onChanged ], ), ); } }修改Home页面,接收返回数据
打开Settings页面时用await Navigator.push接收返回值,更新显示:class _HomeState extends State<Home> { String _string = '0m'; // 打开设置页面的方法(从Drawer或AppBar触发) void _openSettings() async { final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => Settings()), ); if (result != null && result is SettingsData) { setState(() { _string = result.feet ? '0ft' : '0m'; }); } } // 对应修改NavigationDrawer的跳转逻辑,调用_openSettings即可 }
方法二:使用单例类管理全局状态(适合小型应用)
如果需要多个页面共享状态,且不需要持久化,用单例类存储设置数据。
步骤:
创建全局设置单例类
class AppSettings { static final AppSettings _instance = AppSettings._internal(); bool isFeetChecked = false; bool isMetersChecked = true; factory AppSettings() => _instance; AppSettings._internal(); }修改Settings页面,更新单例数据
class _SettingsState extends State<Settings> { late AppSettings _settings; @override void initState() { super.initState(); _settings = AppSettings(); // 初始化当前状态为单例中的数据 _isFeetChecked = _settings.isFeetChecked; _isMetersChecked = _settings.isMetersChecked; } @override Widget build(BuildContext context) { return Scaffold( // ... 其他代码 CheckboxListTile( title: Text('Distance in feet'), value: _isFeetChecked, onChanged: (bool? value) { setState(() { _isFeetChecked = value ?? false; _isMetersChecked = !_isFeetChecked; // 更新单例中的全局数据 _settings.isFeetChecked = _isFeetChecked; _settings.isMetersChecked = _isMetersChecked; }); }, ), // 另一个Checkbox同理修改 ); } }修改Home页面,获取并显示单例数据
class _HomeState extends State<Home> { String _string = '0m'; late AppSettings _settings; @override void initState() { super.initState(); _settings = AppSettings(); _updateDisplay(); } void _updateDisplay() { setState(() { _string = _settings.isFeetChecked ? '0ft' : '0m'; }); } // 打开设置页面返回后刷新显示 void _openSettings() async { await Navigator.push(context, MaterialPageRoute(builder: (context) => Settings())); _updateDisplay(); } }
方法三:使用SharedPreferences持久化设置(进阶,重启APP保留设置)
如果希望用户设置在APP重启后依然有效,用SharedPreferences存储。
步骤:
添加依赖
在pubspec.yaml中添加:dependencies: shared_preferences: ^2.2.2修改Settings页面,保存/加载设置
import 'package:shared_preferences/shared_preferences.dart'; class _SettingsState extends State<Settings> { bool _isFeetChecked = false; bool _isMetersChecked = true; @override void initState() { super.initState(); _loadSavedSettings(); // 加载之前保存的设置 } // 加载本地存储的设置 Future<void> _loadSavedSettings() async { final prefs = await SharedPreferences.getInstance(); setState(() { _isFeetChecked = prefs.getBool('isFeetChecked') ?? false; _isMetersChecked = !_isFeetChecked; }); } // 保存设置到本地 Future<void> _saveSettings() async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool('isFeetChecked', _isFeetChecked); } @override Widget build(BuildContext context) { return Scaffold( // ... 其他代码 CheckboxListTile( title: Text('Distance in feet'), value: _isFeetChecked, onChanged: (bool? value) { setState(() { _isFeetChecked = value ?? false; _isMetersChecked = !_isFeetChecked; }); _saveSettings(); // 保存设置 }, ), // 另一个Checkbox同理修改 ); } }修改Home页面,加载并显示持久化设置
import 'package:shared_preferences/shared_preferences.dart'; class _HomeState extends State<Home> { String _string = '0m'; @override void initState() { super.initState(); _loadSettings(); } Future<void> _loadSettings() async { final prefs = await SharedPreferences.getInstance(); final isFeet = prefs.getBool('isFeetChecked') ?? false; setState(() { _string = isFeet ? '0ft' : '0m'; }); } // 打开设置页面返回后重新加载 void _openSettings() async { await Navigator.push(context, MaterialPageRoute(builder: (context) => Settings())); _loadSettings(); } }
内容的提问来源于stack exchange,提问作者Kunj Bhuva
相关产品推荐
相关产品推荐

