GlobalKey有一个很实用的功能,可以让我们访问到其挂载的widget,context,state数据,上个栗子: /// 定义色块StatefulWidget class StatefulColorfulTile...debugLabel }) => LabeledGlobalKey(debugLabel); const GlobalKey.constructor() : super.empty();...当我们需要访问GlobalKey时,则调用WidgetsBinding.instance!.buildOwner!....key = widget.key; if (key is GlobalKey) { owner!....会复用取出GlobalKey对应的element(这里需要注意_retakeInactiveElement有先后问题,如果我们复用的widget已经被deactivateChild,那么在_retakeInactiveElement
未经过改装的MaterialApp 可以说MaterialApp基于WidgetsApp 如果对MaterialApp不熟悉,可先看我上一篇文章: Flutter之MaterialApp使用详解...与MaterialApp相比 18个相同字段: 字段 类型 navigatorKey(导航键) GlobalKey onGenerateRoute(生成路由) RouteFactory...= null) return widget.onGenerateRoute(settings); return null; } //下面这里有部分省略 new WidgetsApp...的主题 一般使用BottomNavigationBar、AppBar这些部件,会应用到这个主题 //如果为空使用默认光亮主题 final ThemeData theme = widget.theme...AnimatedTheme( data: theme, isMaterialAppTheme: true, child: new WidgetsApp( key
如果滚动方向是垂直方向,则表示子组件的高度;如果滚动方向为水平方向,则表示子组件的长度。...null,则列表为无限列表。...GridView的默认构造函数: GridView({ Key key, Axis scrollDirection = Axis.vertical, bool reverse = false...key, this.data}): super(key: key); @override Widget build(BuildContext context) { return Container...,返回false即可;如果绘制过程需要依赖外部状态,可以在shouldRepaint()中判断依赖的状态是否改变,如果已改变,则返回true并执行重绘操作,反之则返回false不执行重绘; 2)绘制应尽可能多地进行分层
这不起作用,因为Navigator.of(context)找到BottomNavigatorBar本身的祖先。...MaterialColor只不过是一个有十种不同色调的ColorSwatch```。...1_u3V51SHLSoR4q0_OD45bQg.png 将这些组装起来 现在我们有了我们自己的TabNavigator,让我们回到我们的App并使用它: final navigatorKey = GlobalKey...如果正在呈现的选项卡与当前选项卡不匹配,则offstage属性为true。 我们将navigatorKey [tabItem]传递给TabNavigator,以确保每个选项卡都有一个单独的导航键。...看一下WillPopScope的文档: 注册用户否决尝试的回调以解除封闭的/// [ModalRoute] 在第4行,我们定义一个onWillPop()回调,如果当前导航器可以弹出则返回false,否则返回
而 Element 则就是 Widget 树 中特定位置对应的实例,如下图所示: 上图刚好对应上面的例子: **在没有 key 的情况下,**如果替换掉 第一个和第二个 box 置换,那么第二个就会使用第一个...加上 key 的情况: 加上 key 之后,widget 和 element 会有对应关系,如果 key 没有对应就会重新在同层级下寻找,如果没有最终这个 widget 或者 Element 就会被删除...3,如果大于,则 index 和 index +1 进行互换,小于则 index 和 index-1互换。 4,进行判决处理,如果处于第一个或最后一个时直接 return。...问题 其实在上面最终完成的例子中,还是有一些问题,例如只能是横向的,如果是竖着的,就需要重新修改代码。 并且 x 的坐标是从 0 开始计算的,如果在前面还有一些内容就会出现问题了。...例如如果是竖着的,在最上面有一个 appbar,则就会出现问题。
另外,在继承 widget 时,第一个参数通常 key ,另外,如果 Widget 需要接收自 Widget,那么 child 或者 children 参数通常应该放在参数列表的最后。...在一些场景下,Flutter framework 会将 State 对象重新插入到树中,如果包含次 State 对象的子树在树的一个位置移动到另一个位置时(可以通过 GlobalKey 来实现)。...如果移除之后没有重新插入到树中则紧接着就会调用 dispose() 方法 dispose() 当 State 对象从树中被永久移除时调用;通常子此回调中释放资源 class CounterWidget...static GlobalKey _globalKey= GlobalKey(); ......Scaffold( key: _globalKey , //设置key ... ) 复制代码 注意:使用 GlobalKey 开销很大,如果有其他方案,应该去避免它,另外同一个 GlobalKey
如果两个widget的runtimeType和key属性分别是相等的(==),则新widget通过更新基础element(即,通过使用新的widget调用Element.update)来替换旧widget...当找到新的widget(其键和类型与相同位置的先前widget不匹配),但是在前一帧的树中其他位置有一个具有相同全局键的widget时,该widget的element将移至新位置。..._removeTodo(context, todo); }, ); ObjectKey 如果你有一个生日应用,它可以记录某个人的生日,并用列表显示出来,同样的还是需要有一个滑动删除操作。...globalkey相对而言是比较昂贵的,如果你并不需要globalkey的某些特性,那么可以考虑使用Key、ValueKey、ObjectKey或UniqueKey。...用途2 GlobalKey 能够跨 Widget 访问状态。 在这里我们有一个 Switcher 小部件,它可以通过 changeState 改变它的状态。
Widget,如果标识符相同,则说明 Widget 没有变化,否则说明 Widget 有变化。...假设 UI 刷新前,Widget树 是 A,在 A 里有一个标识符为 a 的 Widget,在 UI 刷新后,重建的 Widget树 是 B,如果 B 里还有标识符为 a 的 Widget,则说明这个...Widget 有 Key 当给 Widget 设置了 Key 时,Flutter 是根据 Key 和 runtimeType 是否相同来判断 Widget 是否有变化。...如果一个 widget 设置了 GlobalKey,那么我们便可以通过globalKey.currentWidget 获得该 widget 对象、globalKey.currentElement 来获得...注意:使用 GlobalKey 开销较大,如果有其他可选方案,应尽量避免使用它。另外,同一个 GlobalKey 在整个 widget 树中必须是唯一的,不能重复。
controller == null && identical(scrollDirection, Axis.vertical), super(key: key); key:当前元素的唯一标识符...addAutomaticKeepAlives:表示是否将列表项包裹在 AutomaticKeepAlive widget 中。(在懒加载时,如果设置了包裹那么在此列表项滑出屏幕外时不会被GC。...---- GridView(网格 View) GridView 可以构建一个网格列表视图 GridView.builder({ Key key, Axis scrollDirection...如果设置为 0.0,表示关闭预加载 semanticChildCount:提供语义信息的孩子的数量 GridView 固定列数 import 'package:flutter/material.dart...ScrollController({ double initialScrollOffset = 0.0, this.keepScrollOffset = true, this.debugLabel
didUpdateWidget() widget重建时,如果新旧 widget 的key相同就会调用此方法 deactivate() 当State对象从树中被移除时,会调用此方法。...如果移除后没有重新插入到树中则紧挨着会调用 disponse 方法。 dispose() 当State对象从树中被永久移除时调用,通常用于在此回调中释放资源。...如果 一个 widget 设置了 GlobalKey,那么我们便可以通过 globalKey.currentWidget 获得该 widget 对象,globalKey.currentElement 来获得...widget对应的 element 对象,如果当前 widget 是 StatefulWidget ,则可以通过 globalKey.currentState 来获得该 widget 对应的 state...需要注意的是:GlobalKey开销较大,如果有其他可选方案,应尽量避免使用它,另外同一个 GlobalKey 在整个 widget树中必须是唯一,不能重复。
如果你想让它可拖动怎么办。本教程有一个示例,说明您需要做什么才能创建浮动操作按钮,只要它位于父小部件内,就可以将其拖动到屏幕周围的任何位置。 创建可拖动的浮动操作按钮 我们将为这样的小部件创建一个类。...如果我们忽略这一点,用户可以将按钮拖到父框之外。这意味着有必要知道父级的宽度和高度。...如果新偏移量低于最小偏移量,则必须将该值设置为最小偏移量。如果新偏移量大于最大偏移量,则必须将该值设置为最大偏移量。您需要对 x 轴和 y 轴执行此操作。..._key = GlobalKey(); bool _isDragging = false; late Offset _offset; late Offset _minOffset;...(); } }, child: Container( key: _key, child: widget.child
StatelessWidget({ Key key }) : super(key: key); -------->[createElement方法复写Widget方法,使用StatelessElement...) - - - ---- 二、Flutter卡牌游戏Start 接下来会列出一长串属性,并挑选些简单的属性测试一下 如果你觉得及其无聊,列属性的地方可以跳过,基本上每三个做一个小测试...,还好我flex布局玩的挺好:有兴趣的可看这里 Flow用起来麻烦很多,但可控制,灵活性更好,如果不是什么逆天改命的布局,Warp应该够了 Wrap({ Key key, this.direction...GridView.count({ Key key, Axis scrollDirection = Axis.vertical, bool reverse = false,...> children = const Widget>[], int semanticChildCount, ---- 水平GridView 竖直GridView //竖直GridView
= null) { /// 移除加载中的图片监听,次数如果是最后一个,则 _LiveImage 也会被释放 pendingImage.removeListener();...image,如果 image 为空,则 RawImage 的大小为 Size(0,0) // 如果加载完成,则会被刷新和展示 Widget result = RawImage( //...debugLabel, width: widget.width, height: widget.height, scale: _imageInfo?.scale ??...kReleaseMode) { completer.debugLabel = '${completer.debugLabel} - Resized(${key._width}×${key....如果本文有帮助到你的地方,不胜荣幸,如有文章中有错误和疑问,欢迎大家提出! 参考资料 Flutter图片加载优化探索 Flutter 图片加载 省略.....
注意:如果您希望重建与此状态关联的Widget,则此方法基本上是'initState'的替代!...随意点开一个Widget,就会发现,可以传递一个参数Key.那这个Key到底是干啥子,有什么用呢?...[image.png] Flutter是受React启发的,所以Virtual Dom的diff算法也参考过来了(应该是略有修改),在diff的过程中如果节点有Key来比较的话,能够最大程度重用已有的节点...需要注意的是:不要滥用GlobalKey,如果有更好的方式的,请使用其他方式来传递状态。 这里有一个例子是 通过给Scaffold添加GolbalKey。...还有一个场景是,过渡动画,当两个页面都是相同的Widget时,也可以使用GlobalKey。undefined总结这边文章,我们对StateFulWidget有了升入的认识。
Image内部维护了一个 ImageProvider对象,ImageProvider则真正维护整个图片加载的工作。...debugLabel, width: widget.width, height: widget.height, scale: _imageInfo?....onError }) { // 根据key从正在加载的map里获取缓存,如果有直接返回 ImageStreamCompleter?...不同的 ImageProvider 子类有自己的实现。...我们可以认识到几个问题 Flutter 本身是有图片的内存缓存。也是按照 LRU 的算法去管理缓存的。并且缓存池有阈值,我们可以自己去设置我们想要的内存阈值。
key}) : super(key: key); @override Widget build(BuildContext context) { return GameWidget(game...key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp(... navKey = GlobalKey(debugLabel: 'navKey'); static NavigatorState?...key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp(...在 Flame 中展示浮层 有时我们有显示浮层的需求,比如暂停游戏时,显示暂停面板。不然用户不小心碰到了暂停键,有可能不知所措,显示一个浮层界面可以更好的引导交互。
但是如果在两个乒乓球上分别标出字母A和B,那就一目了然了,这就是Key存在的意义。这时你可能会问,如果不使用Key来做唯一的标识,拿错了就拿错了呗,有什么后果吗?...没有Key的时候会发生什么 先来看个例子:一个Column布局中垂直放置两个同类型的stateful有状态组件,其中color直接作为statefulWidge的属性,而count存在于state中。...当Widget改变的时候,Element会通过组件类型以及对应的Key来判断旧的Widget和新的Widget是否一致: 1,如果某一个位置的旧Widget和新Widget不一致,就会重新创建Element...发现Widget树中第一位置上的最新的Widget和它创建的RenderObject中旧的widget不一致了(因为Key不一样了),此时Element不会立刻被销毁,而是会继续在同级目录下逐个查找,如果能找到和旧的...如上所述,Element树中第一位置存储了数字2的Element会继续对比Widget树中第二位置的widget,此时发现一致(因为Key一致),则建立对应关系并复用Element;同理,Element
key, }) : super(key: key); @override Widget build(BuildContext context) { return GridView(...key, }) : super(key: key); @override Widget build(BuildContext context) { return GridView.builder...则使用传入的itemBuilder函数通过index参数实时创建Widget。...NotificationListener是一个Widget,模板参数T是想监听的通知类型,如果省略,则所有类型通知都会被监听,如果指定特定类型,则只有该类型的通知会被监听。...该回调可以返回一个布尔值,代表是否阻止该事件继续向上冒泡,如果为true时,则冒泡终止,事件停止向上传播,如果不返回或者返回值为false 时,则冒泡继续。
注意:如果您希望重建与此状态关联的Widget,则此方法基本上是'initState'的替代!...随意点开一个Widget,就会发现,可以传递一个参数Key.那这个Key到底是干啥子,有什么用呢?...image.png Flutter是受React启发的,所以Virtual Dom的diff算法也参考过来了(应该是略有修改),在diff的过程中如果节点有Key来比较的话,能够最大程度重用已有的节点...需要注意的是:不要滥用GlobalKey,如果有更好的方式的,请使用其他方式来传递状态。 这里有一个例子是 通过给Scaffold添加GolbalKey。...还有一个场景是,过渡动画,当两个页面都是相同的Widget时,也可以使用GlobalKey。 ---- 总结 这边文章,我们对StateFulWidget有了升入的认识。
= null) _owner = parent.owner; if (widget.key is GlobalKey) { final GlobalKey key =...widget.key; key....当更新后的 Widget 为 null 时,对应的子节点已经移除,如果当前 child 不为 null,则直接 remove 掉; 当更新后的 Widget 不为 null 且当前 child 为 null...时,说明新 Widget 是新创建的,则 inflateWidget 创建子节点; 当更新后的 Widget 不为 null 且当前 child 也不为 null 该节点存在时,若 child.widget...is GlobalKey) { final GlobalKey key = widget.key; key.