我正在尝试根据使用以下代码存储在共享首选项中的值来切换抽屉选项卡。
当不使用 memoizer 但未来的构建器永远运行时,代码工作正常。
如果我使用 memorizer,未来的构建器仍然至少运行两次(不是永远),但是 get 和 set 函数不起作用,新值不会更新,也不会通知小部件。
我需要一些方法来永远停止运行未来的构建器,并通过触发其中存在的 get 和 set 函数来相应地通知用户
通知程序类
class SwitchAppProvider extends ChangeNotifier {
switchApp(value) async {
// initialize instance of sharedpreference
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('key', value);
notifyListeners();
}
Future<bool?> getValue() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final value = prefs.getBool('key');
return value;
}
}
抽屉
Widget _buildDrawer() {
return ChangeNotifierProvider<SwitchAppProvider>(
create: (context) => SwitchAppProvider(),
child: Consumer<SwitchAppProvider>(
builder: (context, provider, _) {
return Container(
width: 260,
child: Drawer(
child: Material(
color: Color.fromRGBO(62, 180, 137, 1),
child: ListView(
children: <Widget>[
Container(
padding: AppLandingView.padding,
child: Column(
children: [
const SizedBox(height: 10),
FutureBuilder(
future: provider.getValue(),
builder: (BuildContext context,
AsyncSnapshot<dynamic> snapshot) {
if (snapshot.data == true) {
return _buildMenuItem(
text: 'widget1',
icon: Icons.add_business,
onTap: () {
provider.switchApp(false);
},
);
} else {
return _buildMenuItem(
text: 'widget2',
icon: Icons.add_business,
onTap: () {
provider.switchApp(true);
},
);
}
},
),
],
),
),
],
),
),
),
);
},
),
);
}
脚手架
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: _buildDrawer(),
);
}
更新
我进一步分析,问题在于provider.getValue(),如果我在返回值之前使用notifyListeners() 未来构建器将永远运行
我删除了它,未来的构建器不会永远运行,但它不会更新其他小部件。
情景是
小部件 1
- 包含一个抽屉
- 有一个按钮来切换应用程序
- 使用共享首选项(setValue() 函数)设置点击值,并通知侦听器
- 在小部件 1 中,通知程序运行良好,并且在点击调用 setValue() 时更改了抽屉按钮选项。
- 小部件 1 中的所有内容都已解决,因为它的调用 setValue() 因此触发了 notifyListeners() 并重新渲染了小部件 1
小部件 2
仅从共享偏好中获取价值(getValue() 函数)。getValue 函数不能使用 notifyListeners(),如果使用 futurebuilder 将永远运行
小部件 2 没有设置任何值,因此它不使用 setValue() 因此它没有得到通知
当在小部件 1 中触发点击 setValue() 时,我如何通知小部件 2
即 widget1 使用 setValue() 函数设置应用程序
widget2 从 getValue() 函数中获取值并得到通知
更新 2
class SwitchAppProvider with ChangeNotifier {
dynamic _myValue;
dynamic get myValue => _myValue;
set myValue(dynamic newValue) {
_myValue = newValue;
notifyListeners();
}
setValue(value) async {
// initialize instance of sharedpreference
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('key', value);
notifyListeners();
}
SwitchAppProvider(){
getValue();
}
Future<void> getValue() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
myValue = prefs.getBool('key');
}
}
小部件 2
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: SwitchAppProvider(),
child: Consumer<SwitchAppProvider>(
builder: (BuildContext context, SwitchAppProvider provider, _) {
if (provider.myValue == true) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return Container(
child: Text('provider.myValue'));
}
})
);
}
}
_buildMenuItem
// helper widget to build item of drawer
Widget _buildMenuItem({
required String text,
required IconData icon,
required GestureTapCallback onTap,
}) {
final color = Colors.white;
final hoverColor = Colors.white;
return ListTile(
leading: Icon(icon, color: color),
title: Text(text, style: TextStyle(color: color, fontSize: 18)),
hoverColor: hoverColor,
onTap: onTap,
);
}