1、Flutter Tips - Widget Key;

  当WidgetWidget Tree中移动时,Key会保留其状态。它们可用于保留用户的滚动位置等信息。

Key的种类

   Key主要分为Local KeysGlobal Keys;

Local Keys
  • ValueKey : ValueKey('value')
  • ObjectKey : ObjectKey(MutableRectangle(1,2,3,4))
  • UniqueKey : UniqueKey()
  • PageStorageKey : PageStorageKey(scrollLocation)
Global Keys
  • GlobalKey : GlobalKey()

什么时候使用Key

  大多数情况下,我们并不需要使用Key。但是如果你发现自己需要添加、删除或者重新排序处于某种状态的相同类型的Widget集合就会用到Key

import 'package:flutter/material.dart';

class KeyDemoApp extends StatelessWidget{

  @override
  Widget build(BuildContext context) => MaterialApp(
    home: _HomePage(),
  );
}


class _HomePage extends StatefulWidget{
  @override
  State<StatefulWidget> createState() =>_HomePageState();
}

class _HomePageState extends State<_HomePage>{
  List<Widget> _widgets;

  @override
  void initState() {
    super.initState();
    _widgets= [
        RectStateless(Color.fromARGB(255, 0, 0, 0)),
        RectStateless(Color.fromARGB(255, 255, 0, 0))
    ];
  }
  @override
  Widget build(BuildContext context) => Scaffold(
    body:  Center(
      child: Row(children: _widgets,),
    ),
    floatingActionButton: FloatingActionButton(onPressed: swapWidget),
  );


  void swapWidget(){
    setState(() {
      _widgets.insert(1, _widgets.removeAt(0));
    });
  }
}

class RectStateless extends StatelessWidget{
  final Color _bg;
  RectStateless(this._bg,[Key key]):super(key:key);

  @override
  Widget build(BuildContext context) {
    return  Container(color:_bg,
      width: 100,
      height: 100,
    );
  }
}

复制代码

  在上面的代码中,如果点击按钮则两个Widget可以自由的更换位置。如果将两个Widget更换为StatefulWidgetWidget后:

class RectStateful extends StatefulWidget{
 final Color _bg;
 RectStateful(this._bg,[Key key]):super(key:key);
 @override
 State<StatefulWidget> createState() =>RectStatefulState(_bg);

}

class RectStatefulState extends State<RectStateful>{
 final Color _bg;
 RectStatefulState(this._bg);

 @override
 Widget build(BuildContext context) {
   return  Container(color:_bg,
     width: 100,
     height: 100,
   );
 }
}
复制代码

当点击时两个色块都不会交换,当添加上Key后则又可以交换位置:

_widgets= [
 RectStateful(Color.fromARGB(255, 0, 0, 0),UniqueKey()),
 RectStateful(Color.fromARGB(255, 255, 0, 0),UniqueKey())
];
复制代码

  从上面的例子可以看出: 如果集合中的整个小部件子树是无状态的,则不需要使用Key。

Key的运作方式

  在Stateless的例子中,Row为子Widget提供了一组有序的插槽。对于每个小部件,Flutter都会构建一个相应的Element,Element tree只会保存每个Widget类型以及对子Element的引用信息。可以将Element tree视为Flutter应用程序的骨架,它显示了应用程序的结构。当交换Row中的Widget时,Flutter会遍历Element tree来查看骨架结构是否相同,即检查新的Widget是否和旧的Widget的类型和Key是否相同,如果是一样的,它会更新对新Widget的引用,对于其他Widget也是对应的步骤。Stateless的例子中,Widget没有Key,Flutter只会检查其类型。

  在Stateful没有Key例子中,每个Widget都会有一个State对象来保存相应的信息,这些信息而不是存储在小部件本身中。Flutter会检查Row小部件的类型,类型是一样的会更新引用,第二个Widget也如此。Flutter会遍历Element tree以及其对应的State来确定在设备上显示的实际内容。因此,看起来相应的Widget并没有正确的交换。

  在有KeyStateful例子中,向小部件添加来key的属性。在交换Row小部件时会像之前一样匹配。但是新的Widget的密钥和之前小部件Element对应的Key不匹配。因此,Flutter会停用这些Element,从第一个不匹配的Element开始,然后Flutter会查看不匹配的子项,查找具有相同密钥的Element,它会找到匹配项,并更新对相应Widget的引用。然后Flutter会为后续的子项做相同的事情。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值