Как избавиться от глобального ключа от провайдера с помощью Flutter Web?

Хочу построить ящик с полотном флаттера. Но в дереве виджетов обнаружен Duplicate GlobalKey. экземпляр перемещен в новое место. Ключ был:

  • [LabeledGlobalKey # c9754]

Переродление GlobalKey:

  • MainScreen (зависимости: [MediaQuery], состояние: _MainScreenState # dc897) GlobalKey может быть указан только для одного виджета за раз в дереве виджетов.

    import 'package: flutter / material.dart';

    класс MenuController с ChangeNotifier {GlobalKey _scaffoldKey = GlobalKey ();

    GlobalKey<ScaffoldState> get scaffoldKey => _scaffoldKey;
    
    void controlMenu() {
      if (!_scaffoldKey.currentState!.isDrawerOpen) {
        _scaffoldKey.currentState!.openDrawer();
      }
    }
    
    // void disposeKey() {
    //   _scaffoldKey.currentState.();
    // }
    

    }

    class _MainScreenState расширяет состояние {@override void initState () {print ('init CALLED- GAME ---'); super.initState (); }

    @override
    void dispose() {
      print('DISPOSE CALLED- GAME---');
      context.read<MenuController>().scaffoldKey.currentState!.dispose();
      super.dispose();
    }
    
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        key: context.read<MenuController>().scaffoldKey,
        drawer: SideMenu(),
        body: SafeArea(
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // We want this side menu only for large screen
              if (Responsive.isDesktop(context))
                Expanded(
                  // default flex = 1
                  // and it takes 1/6 part of the screen
                  child: SideMenu(),
                ),
              Expanded(
                // It takes 5/6 part of the screen
                flex: 5,
                child: DashboardScreen(),
              ),
            ],
          ),
        ),
      );
    }}
    

затем хотите повторно использовать ключ из другого виджета

class ProductsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: context.read<MenuController>().scaffoldKey,
      drawer: SideMenu(),
      body: SafeArea(
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // We want this side menu only for large screen
            if (Responsive.isDesktop(context))
              Expanded(
                // default flex = 1
                // and it takes 1/6 part of the screen
                child: SideMenu(),
              ),
            Expanded(
              // It takes 5/6 part of the screen
              flex: 5,
              child: ProductsListScreen(),
            ),
          ],
        ),
      ),
    );
  }
}

и получил ошибку

Для навигации внутри виджета SideMenu используйте

Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => ProductsScreen(),
                ),
              );

person Adil    schedule 09.07.2021    source источник
comment
насколько я помню, это можно исправить, переназначив значение вашему глобальному ключу в каждой сборке   -  person Adnan    schedule 09.07.2021
comment
спасибо, как это сделать? попробовал context.read ‹MenuController› () .scaffoldKey.currentState.dispose при удалении context.read ‹MenuController› () .scaffoldKey.currentState.build (context) при инициализации, но не работает   -  person Adil    schedule 09.07.2021


Ответы (1)


Вам не нужно вручную утилизировать GlobalKey. Главное требование - их нельзя дважды вставить в дерево виджетов. Это не относится к другим ключам (LocalKeys):

// this is allowed
Row(
  children: [
    SizedBox(key: Key('hello')),
    Container(key: Key('hello')),
  ],
)

// this is not
final key = GlobalKey<ScaffoldState>();
Row(
  children: [
    Scaffold(key: key),
    Scaffold(key: key),
  ],
)

Распространенная причина нарушения этого правила - анимация. Пока воспроизводится анимация между одной страницей и другой, обе страницы находятся в дереве виджетов, и если они имеют одинаковый GlobalKey, будет выдана ошибка.

Вызов globalKey.currentState!.dispose() фактически удаляет State связанного виджета. Вы не должны сами называть это.

Вместо этого предоставьте новый GlobalKey второму поддереву или удалите старый перед переходом на новую страницу.

person cameron1024    schedule 09.07.2021