首页 > 解决方案 > 关于 Flutter 的 Key 有一些地方我不是很了解

问题描述

我是在看了一个解释 Flutter's Key 的视频后练习的。

https://api.flutter.dev/flutter/foundation/Key-class.html

该视频展示了一个使用特定颜色更改容器位置的示例。(约 1 分 50 秒)

在视频中,statefulwidget 说没有密钥,位置不会改变。

但是我自己编写了示例代码并确认它可以在没有给有状态小部件密钥的情况下工作。

我想我写错了示例代码。下面是我写的代码。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: KeyPractice(),
    );
  }
}

class StatefulColorfulTile extends StatefulWidget {
  StatefulColorfulTile({@required this.color});

  final Color color;

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

class _StatefulColorfulTileState extends State<StatefulColorfulTile> {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: widget.color,
    );
  }
}

class KeyPractice extends StatefulWidget {
  @override
  _KeyPracticeState createState() => _KeyPracticeState();
}

class _KeyPracticeState extends State<KeyPractice> {
  List<Widget> tiles;

  @override
  void initState() {
    super.initState();
    tiles = [
      StatefulColorfulTile(
        color: Colors.blueAccent,
      ),
      StatefulColorfulTile(
        color: Colors.amber,
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Row(
          children: tiles,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(
          Icons.autorenew,
        ),
        onPressed: () {
          setState(() {
            tiles.insert(1, tiles.removeAt(0));
          });
        },
      ),
    );
  }
}

上述代码相互交换位置。

当视频中的有状态小部件未分配键时,小部件如何相互重新定位的示例会发生什么?

而且我知道该密钥仅适用于 Stateful 小部件,Stateless 是否使用该密钥?

而且我知道 Key 仅适用于 Stateful 小部件。我想知道无状态小部件是否使用密钥。

如果我理解错了,请教我。

标签: flutterflutter-widget

解决方案


您将颜色存储在Stateof 中KeyPractice。他们使用的示例将其存储在State孩子的 中,在您的情况下:StatefulColorfulTile

下面是使用键正确重新定位小部件的示例,就像您尝试做的那样。我的示例最终与这篇中等文章中显示的非常相似。在此处删除键可防止小部件反映颜色交换,但使用键可实现预期行为。

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: KeyPractice(),
    );
  }
}

class StatefulColorfulTile extends StatefulWidget {
  StatefulColorfulTile({Key key}) : super(key: key);
  
  @override
  _StatefulColorfulTileState createState() => _StatefulColorfulTileState();
}

class _StatefulColorfulTileState extends State<StatefulColorfulTile> {
  final Color myColor = UniqueColorGenerator.getColor();
  
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: myColor,
    );
  }
}

class KeyPractice extends StatefulWidget {
  @override
  _KeyPracticeState createState() => _KeyPracticeState();
}

class _KeyPracticeState extends State<KeyPractice> {
  List<Widget> tiles;

  @override
  void initState() {
    super.initState();
    tiles = [
      StatefulColorfulTile(key: UniqueKey()),
      StatefulColorfulTile(key: UniqueKey()),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Row(
          children: tiles,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(
          Icons.autorenew,
        ),
        onPressed: () {
          setState(() {
            tiles.insert(1, tiles.removeAt(0));
          });
        },
      ),
    );
  }
}


class UniqueColorGenerator {
  static Random random = new Random();
  static Color getColor() {
    return Color.fromARGB(255, random.nextInt(255), random.nextInt(255), random.nextInt(255));
  }
}

推荐阅读