“This is the 28th day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

  • We created in shortcutstateless Widgetorstateful WidgetWill let us create onekeyI haven’t talked about it before, so let’s talk about it.

Example 1.

We’re going to create a listView and add three cells, give it a random color, and when we click remove the first element,

class _keyDemoState extends State<keyDemo>{
  List<String> names = ['1111'.'2222'.'3333'];

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Scaffold(
        appBar: AppBar(),
        body: ListView(
          children: names.map((str) {
            return listCell(name: str,);
          }).toList(),

        ),
    floatingActionButton: FloatingActionButton(
    onPressed: (){

       names.removeAt(0);
       setState(() {

       });
    },
    tooltip: 'delete',
    child: constIcon(Icons.delete), ), ) ); }}Copy the code

The style of the cell

class listCell extends StatelessWidget {
  final String? name;
  final Color bgcolor = Color.fromRGBO(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1); listCell({Key? key,this.name,}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
        height: 44, child: ListTile( tileColor:bgcolor , title: Text(name!) )); }}Copy the code

We hit Delete to remove the first element, but after setState we rebuild it, and the color is again random

This is clearly not what we want. Let’s replace the cell with a statefulWidget

Click the delete

We found that the data changed, but the color did not. We deleted the color of the last one and the text of the first one.

  • That’s because when you delete the first data,Element corresponding to the WidgetIt hasn’t changed;
  • whileElementIn the correspondingThe State referenceIt hasn’t changed;
  • In the updateWidgetThe time,WidgetIt uses the sameElementIn theState;

2. Key usage

We add a key to our statefulWidget

Click delete to get the effect we want

Let’s look at the source code

Element does not update when our [runtimeType] and [key] are unchanged. When we delete the first widget, we use the previous Element because the key is empty and the [runtimeType] is the same.

If we use random keys

After deleting

We also verify that every time our key changes, Element forces a refresh and the corresponding State is recreated

3. Key classification

Key is an abstract class with a factory constructor that returns the key

Key has two subclassesLocalKeyandGlobalKey

3.1 LocalKey

There are three main subclasses of LocalKey

  • ValueKey:

    • ValueKey is used when we have a specific value as the key, such as a string, number, and so on
  • ObjectKey:

    • If two models have the same type, it is not appropriate to use type as their key
    • We can create a model object and use the object as the key
  • UniqueKey

    • If we want to ensure that the key is unique, we can use UniqueKey;
    • For example, we used random numbers to ensure that the key is different, so we can use UniqueKey;

3.2 GlobalKey

Can help us access information about a Widget, including widgets or objects such as State or Element

class GlobalKeyDemo extends StatelessWidget {
  final GlobalKey<_ChildPageState> _globalKey = GlobalKey();

  GlobalKeyDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GlobalKeyDemo'), ), body: ChildPage( key: _globalKey, ), floatingActionButton: FloatingActionButton( onPressed: () { _globalKey.currentState! .setState(() { _globalKey.currentState! .data ='old:'+ _globalKey.currentState! .count.toString(); _globalKey.currentState! .count++; }); }, child:constIcon(Icons.add), ), ); }}class ChildPage extends StatefulWidget {
  const ChildPage({Key? key}) : super(key: key);

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

class _ChildPageState extends State<ChildPage> {
  int count = 0;
  String data = 'hello';
  @override
  Widget build(BuildContext context) {
    returnCenter( child: Column( children: [ Text(count.toString()), Text(data), ], ), ); }}Copy the code