如何使用 Flutter Web 处理来自提供商的全局密钥?
Posted
技术标签:
【中文标题】如何使用 Flutter Web 处理来自提供商的全局密钥?【英文标题】:How dispose Global key from provider with flutter web? 【发布时间】:2021-09-19 11:09:59 【问题描述】:想用 Flutter web 构建抽屉。但是得到了 在小部件树中检测到重复的 GlobalKey。 实例被移动到新位置。关键是:
[LabeledGlobalKey#c9754]GlobalKey 重设是:
MainScreen(依赖项:[MediaQuery],状态:_MainScreenState#dc897) 在小部件树中一次只能在一个小部件上指定 GlobalKey。
导入'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.();
//
类 _MainScreenState 扩展状态 @覆盖 无效初始化状态() 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(),
),
);
【问题讨论】:
我记得这可以通过在每次构建时为全局键重新分配一个值来解决 谢谢,a 怎么办?在初始化时尝试了 context.read您无需手动处理GlobalKey
。主要要求是它们不能两次插入到小部件树中。其他键不是这种情况(LocalKey
s):
// 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),
],
)
违反此规定的一个常见原因是动画。在播放一个页面和另一个页面之间的动画时,两个页面都在widget树中,如果它们具有相同的GlobalKey
,则会抛出错误。
调用globalKey.currentState!.dispose()
实际上会释放关联小部件的State
。你不应该自己调用它。
相反,为第二个子树提供一个新的GlobalKey
,或者在导航到新页面之前删除旧的。
【讨论】:
以上是关于如何使用 Flutter Web 处理来自提供商的全局密钥?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Django 为 Flutter Web 应用程序提供服务?
如何在 Flutter 中使用 Provider 显示来自 ChangeNotifier 的错误
如何在 Flutter Web 中使用 Skia/CanvasKit?