首页 > 其他分享 >一统天下 flutter - widget 基础: Key - 键

一统天下 flutter - widget 基础: Key - 键

时间:2023-04-28 12:44:07浏览次数:46  
标签:widget Key color MyStatefulWidget Widget GlobalKey key flutter

源码 https://github.com/webabcd/flutter_demo
作者 webabcd

一统天下 flutter - widget 基础: Key - 键

示例如下:

lib\widget\basic\key.dart

/*
 * Key - 键
 *
 * LocalKey 和 GlobalKey 用于让 element 找到 widget
 * GlobalKey 也可以用于获取对应的 Widget/State/RenderObject
 *
 * 1、LocalKey - 这是一个抽象类,用于标识 Widget,要求在 widget 树中同一级必须唯一
 *   a) ValueKey - 值类型的 LocalKey,判断 key 是否相同时按照值是否相等判断
 *   b) ObjectKey - 引用类型的 LocalKey,判断 key 是否相同时按照指针是否相等判断
 *   c) UniqueKey - 自动生成的唯一 LocalKey,每次都会生成不同的唯一 key
 * 2、GlobalKey - 用于标识 Widget,要求在整个应用程序中必须唯一
 */

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_demo/helper.dart';


class KeyDemo extends StatefulWidget {
  const KeyDemo({Key? key}) : super(key: key);

  @override
  _KeyDemoState createState() => _KeyDemoState();
}

class _KeyDemoState extends State<KeyDemo> {

  /// 没有指定 key
  List<Widget> widgets1 = [
    _MyStatefulWidget(color: Colors.red),
    _MyStatefulWidget(color: Colors.green),
  ];

  /// 指定了 ValueKey
  /// ValueKey, ObjectKey 要求在树的同一级上必须唯一
  /// 如果是 UniqueKey 的话,则每次 Widget 树变化后,都会生成唯一的 key,所以原 Element 找不到 key 相同的 Widget,所以就会重新创建新的 Element,原 Element 会被销毁
  List<Widget> widgets2 = [
    _MyStatefulWidget(color: Colors.red, key: ValueKey(1),),
    _MyStatefulWidget(color: Colors.green, key: ValueKey(2),),
  ];

  /// 指定了 GlobalKey
  List<Widget> widgets3 = [
    _MyStatefulWidget(color: Colors.red, key: GlobalKey(),),
    _MyStatefulWidget(color: Colors.green, key: GlobalKey(),),
  ];

  /// 指定了 GlobalKey
  /// 如果定义了 GlobalKey<T> 中的 T 则,则后续通过 GlobalKey 的 currentState 就能直接拿到类型为 T 的 State
  final GlobalKey _globalKey1 = GlobalKey();
  final GlobalKey<_MyStatefulWidgetState> _globalKey2 = GlobalKey<_MyStatefulWidgetState>();
  List<Widget> widgets4 = [ ];

  @override
  void initState() {
    super.initState();

    widgets4 = [
      _MyStatefulWidget(color: Colors.red, key: _globalKey1,),
      _MyStatefulWidget(color: Colors.green, key: _globalKey2,),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        GestureDetector(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: widgets1,
          ),
          onTap: () {
            /// 颜色会调换,数字不会调换
            /// 因为颜色保存在 Widget 中,数字保存在 State 中(注:State 是保存在 Element 树中的)
            /// Widget 树变化后,Element 会从同级树的同样的位置开始找类型相同的 Widget(不会在父级或子级查找)
            widgets1.insert(0, widgets1.removeAt(1));
            setState(() {});
          },
        ),

        GestureDetector(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: widgets2,
          ),
          onTap: () {
            /// 颜色会调换,数字也会调换
            /// Widget 树变化后,Element 会从同级树的同样的位置开始找 key 相同的 Widget(不会在父级或子级查找)
            widgets2.insert(0, widgets2.removeAt(1));
            setState(() {});
          },
        ),

        GestureDetector(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: widgets3,
          ),
          onTap: () {
            /// 颜色会调换,数字也会调换
            /// Widget 树变化后,Element 会从整个应用程序中找 key 相同的 Widget(即使层级发生变化也能找到)
            widgets3.insert(0, Center(child: widgets3.removeAt(1)));
            setState(() {});
          },
        ),

        GestureDetector(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: widgets4,
          ),
          onTap: () {
            widgets4.insert(0, widgets4.removeAt(1));

            /// 通过 GlobalKey 可以获取对应的 Widget/State/RenderObject
            var widget = _globalKey1.currentWidget as _MyStatefulWidget;
            var state = _globalKey1.currentState as _MyStatefulWidgetState;
            var box = _globalKey1.currentContext?.findRenderObject() as RenderBox;
            log("color:${widget.color}, state:${state._number}, globalOffset:${box.localToGlobal(Offset.zero)}, size:${box.size}");

            /// 如果定义 GlobalKey 时指定了 GlobalKey<T> 中的 T 则这里通过 currentState 就能直接拿到类型为 T 的 State
            var _ = _globalKey2.currentState?._number;

            setState(() {});
          },
        ),
      ],
    );
  }
}

class _MyStatefulWidget extends StatefulWidget {
  const _MyStatefulWidget({Key? key, required this.color}) : super(key: key);

  final Color color;

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<_MyStatefulWidget> {

  final Random _random = Random();
  int _number = 0;

  @override
  void initState() {
    super.initState();

    _number = _random.nextInt(100);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      width: 50,
      height: 50,
      color: widget.color,
      child: MyText("$_number"),
    );
  }
}

源码 https://github.com/webabcd/flutter_demo
作者 webabcd

标签:widget,Key,color,MyStatefulWidget,Widget,GlobalKey,key,flutter
From: https://www.cnblogs.com/webabcd/p/flutter_lib_widget_basic_key.html

相关文章

  • pyqt5-QListWidget
    1、介绍list组件,或者说列表组件。2、类和初始化classQListWidget(QListView):快速查询:QListWidget(parent:typing.Optional[QWidget]=None)addItem(self,aitem:QListWidgetItem)addItem(self,label:str)addItems(self,labels:Iterable[str])clear(self)closeP......
  • Hadoop启动集群报错:Starting namenodes on [hadoop01] hadoop01: root@hadoop01: Per
    搭建三个hadoop集群的时候,master没有启动namenode和datanode,报错:Startingnamenodeson[hadoop01]hadoop01:root@hadoop01:Permissiondenied(publickey,gssapi-keyex,gssapi-with-mic,password).Startingdatanodeshadoop01:root@hadoop01:Permissiondenied(publicke......
  • ansible 第一次批量导入ssh-key
    适用环境:所有主机具有相同的用户名和密码实现方式:通过ansiblehosts文件读取主机列表通过expect自动应答脚本出处:githubkubeasz\tools#!/bin/bash#此脚本为批量部署服务器sshkey使用#set-x#checkargscountiftest$#-ne3;thenecho-e"\nUsag......
  • questions_02:【KeyError: 'mobile_phone'[27/Apr/2023 21:42:21] "POST /register/ H
    BUG在成功注册之后,如果填写相同的信息,会报出一个【KeyError:'mobile_phone'[27/Apr/202321:42:21]"POST/register/HTTP/1.1"50086526】的bug,原因是我们的cleaned_data中的数据是按照fields中的顺序去校验成功之后添加的,所以当出现相同的数据时候cleaned_data前面几个字......
  • List与HashMap区别,key,value,感谢火龙果,dgqbcht,awusoft帮助
    首先要感谢不想要妮称,dgqbcht,awusoft友情帮助Map是一个映射,是key-value值对.Map在java1.0以后进行了修改,使其能够与普通的集合相融.在Map的内部定义了内部接口Entry,主要就是要讲key和value以集合(Set)的形式来体现.List是集合的一个分支,是一个接口.List中的元素有顺序(输......
  • ansible推送文件到目标主机时报错 UNREACHABLE! | Permission denied (publickey,gssa
    问题现象:[root@linlin]#ansibleall-mcopy-a'src=/etc/ansible/lin/test.txtdest=/home/'192.168.12.203|UNREACHABLE!=>{"changed":false,"msg":"Failedtoconnecttothehostviassh:[email protected]:Pe......
  • 一统天下 flutter - widget 布局类(可以有多个子): CustomMultiChildLayout - 自定义多
    源码https://github.com/webabcd/flutter_demo作者webabcd一统天下flutter-widget布局类(可以有多个子):CustomMultiChildLayout-自定义多组件布局示例如下:lib\widget\layout\custom_multi_child_layout.dart/**CustomMultiChildLayout-自定义多组件布局*......
  • 一统天下 flutter - widget 容器类(只能有一个子): CustomSingleChildLayout - 自定义单
    源码https://github.com/webabcd/flutter_demo作者webabcd一统天下flutter-widget容器类(只能有一个子):CustomSingleChildLayout-自定义单组件布局示例如下:lib\widget\container\custom_single_child_layout.dart/**CustomSingleChildLayout-自定义单组件布......
  • js 获取对象的key value,放到数组对象中
    letarr=[];if(res.data&&res.data.havePowerComCodes){for(const[key,value]ofObject.entries(res.data.havePowerComCodes)){constobj={......
  • Flutter的路在哪里?
    跨平台技术现已成为企业提升研发效率和动态化能力,抢占新赛道的搏击场。从闲鱼到淘宝,从QQ到微信,从京东到百度,从美团到抖音,BAT等一线互联网大厂在全面拥抱Flutter。2020短短一年里,Flutter在GitHub和StackOverflow已经赶超ReactNative成为开发者首选跨平台框架。尽管Flutter在某些......