Изменение флаттера Состояние ящика с помощью управления состоянием RiverPod

используя 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

без щелчка по значку


person DolDurma    schedule 28.10.2020    source источник


Ответы (1)


вместо Consumer вы должны попробовать использовать ProviderListener, это лучше, когда вы хотите показывать диалоги, панели закусок, push / pop или, в этом случае, открывать ящик. Наконец, вместо того, чтобы создавать конечный поставщик внутри каждого метода сборки, просто создайте его один раз как конечный глобальный параметр, чтобы в каждом виджете, который вы читаете / смотрите, он использует один и тот же экземпляр

/// 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 удалите drawerState, чтобы он использовал тот же глобал, что и ваш HomePage, также при закрытии ящика в какой-то момент вы должны снова сделать состояние ложным.

person EdwynZN    schedule 30.10.2020