通过使用RiverPod
状态管理,我尝试进行自我改进,以学习和使用该状态我做了一个简单的项目,并且试图通过按图标打开Drawer
在AppBar
(位于另一个类和文件中)中,不幸的是,与RiverPod
示例代码一样,我的代码无法正常工作,并且主类也不会在单击图标时触发
我只是想通过单击AppBar
上的图标来打开抽屉
主文件:
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Riverpod Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
final drawerState = StateNotifierProvider<DrawerVisibility>((_)=>DrawerVisibility());
return Consumer(
builder: (context, read, _) {
final state = read(drawerState.state);
print('CLICKED $state');
if(state){
_scaffoldKey.currentState.openDrawer();
}
return Scaffold(
key: _scaffoldKey,
appBar: MyAppBar(),
drawer: Drawer(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
],
),
),
);
},
);
}
}
AppBar
类文件内容:
class MyAppBar extends StatelessWidget with PreferredSizeWidget {
@override
Widget build(BuildContext context) {
final drawerState = StateNotifierProvider<DrawerVisibility>((_)=>DrawerVisibility());
return AppBar(
automaticallyImplyLeading: false,
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
IconButton(icon: Icon(Icons.menu), onPressed: () {
context.read(drawerState).changeDrawerState();
}),
Text('My Sample'),
],
),
);
}
@override
Size get preferredSize => Size.fromHeight(kToolbarHeight);
}
最后是RiverPod
类
class DrawerVisibility extends StateNotifier {
DrawerVisibility() : super(false);
void changeDrawerState() => state = true;
}
另一个问题是我第一次启动应用程序时得到以下输出:
I/flutter (12240): CLICKED false
I/flutter (12240): CLICKED false
无需单击任何图标
答案 0 :(得分:1)
您应该尝试使用Consumer
而不是ProviderListener
,当您要显示对话框,小吃店,推/弹出或在这种情况下打开抽屉时,它会更好。最后,与其在每个构建方法中创建最终的提供程序,不如将其作为最终的全局参数创建一次,因此在您阅读/观看的每个小部件中,它都使用相同的实例
/// Create a final global StateNotifierProvider in your file instead of one inside each widget
final drawerState = StateNotifierProvider<DrawerVisibility>((_)=>DrawerVisibility());
class _MyHomePageState extends State<MyHomePage> {
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return ProviderListener<bool>(
onChange: (context, state) {
if(state) _scaffoldKey.currentState.openDrawer();
//maybe check if the _scaffoldKey is mounted or is the drawer open before doing something
},
provider: drawerState.state,
child: Scaffold(
key: _scaffoldKey,
appBar: MyAppBar(),
drawer: Drawer(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
],
),
),
),
);
}
}
然后在MyAppBar
中删除抽屉状态,以便它使用与HomePage
相同的全局变量,并且在关闭抽屉时,还应再次将状态设置为false