-
Notifications
You must be signed in to change notification settings - Fork 30.7k
Expand file tree
/
Copy pathkey.dart
More file actions
163 lines (150 loc) · 6.14 KB
/
Copy pathkey.dart
File metadata and controls
163 lines (150 loc) · 6.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// @docImport 'package:flutter/semantics.dart';
/// @docImport 'package:flutter/widgets.dart';
library;
import 'package:meta/meta.dart';
import 'diagnostics.dart';
/// A [Key] is an identifier for [Widget]s, [Element]s and [SemanticsNode]s.
///
/// A new widget will only be used to update an existing element if its key is
/// the same as the key of the current widget associated with the element.
///
/// Typically, if no key is provided, the default value is null, meaning the
/// widget is considered unkeyed. In this case, Flutter matches widgets based
/// on their [Widget.runtimeType] and position in the tree during rebuilds.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=kn0EOS-ZiIc}
///
/// Keys must be unique amongst the [Element]s with the same parent.
///
/// Subclasses of [Key] should either subclass [LocalKey] or [GlobalKey].
///
/// A common mistake is to rebuild the widget tree in such a way that Flutter
/// attaches the incorrect State object to an unkeyed StatefulWidget. This can
/// often be solved by using an appropriate [Key] on the [StatefulWidget].
///
/// See [ValueKey], which explains how that class can be used as a solution to a
/// common case of this problem.
///
/// See also:
///
/// * [Widget.key], which discusses how widgets use keys.
@immutable
@pragma('flutter:keep-to-string-in-subtypes')
abstract class Key {
/// Construct a [ValueKey<String>] with the given [String].
///
/// This is the simplest way to create keys.
const factory Key(String value) = ValueKey<String>;
/// Default constructor, used by subclasses.
///
/// Useful so that subclasses can call us, because the [Key.new] factory
/// constructor shadows the implicit constructor.
@protected
const Key.empty();
}
/// A key that is not a [GlobalKey].
///
/// Keys must be unique amongst the [Element]s with the same parent. By
/// contrast, [GlobalKey]s must be unique across the entire app.
///
/// See also:
///
/// * [Widget.key], which discusses how widgets use keys.
abstract class LocalKey extends Key {
/// This constructor enables subclasses to provide const constructors so that
/// they can be used in const expressions.
const LocalKey() : super.empty();
}
/// A key that is only equal to itself.
///
/// This cannot be created with a const constructor because that implies that
/// all instantiated keys would be the same instance and therefore not be unique.
class UniqueKey extends LocalKey {
/// Creates a key that is equal only to itself.
///
/// The key cannot be created with a const constructor because that implies
/// that all instantiated keys would be the same instance and therefore not
/// be unique.
// ignore: prefer_const_constructors_in_immutables , never use const for this class
UniqueKey();
@override
String toString() => '[#${shortHash(this)}]';
}
/// A key that uses a value of a particular type to identify itself.
///
/// A [ValueKey] is equal to another [ValueKey] if, and only if, their values
/// are equal (using [operator==]).
///
/// This class can be subclassed to create value keys that will not be equal to
/// other value keys that happen to use the same value. If the subclass is
/// private, this results in a value key type that cannot collide with keys from
/// other sources. This is useful when keys are used as fallbacks in the same
/// scope as keys supplied from another widget.
///
/// When building widgets from a collection of data, especially when that
/// collection can change over time (e.g., items being inserted, removed, or
/// reordered), keys are used to preserve the association between a widget and
/// the underlying data.
///
/// Without keys, the framework may have no way to distinguish between a change
/// in the data of an existing widget and a structural change in the list. As a
/// result, widgets may be incorrectly updated, and state held by
/// [StatefulWidget]s can be reused for a different piece of data.
///
/// Assigning a key ties the widget subtree to a specific piece of data,
/// allowing the framework to correctly match old and new widgets and preserve
/// state as expected.
///
/// In such cases, a [ValueKey] is typically appropriate, using a value that is
/// stable and unique for each item, such as an identifier from the data model.
///
/// {@tool dartpad}
/// The following example demonstrates the importance of using [ValueKey]s when reordering
/// a list of [StatefulWidget]s.
///
/// ### The Key Difference
/// * **Without Keys**: When the list is reversed, Flutter matches widgets by
/// position. The [State] (the counter) stays in its original spot while the
/// widget's configuration (the color) is swapped. This results in the counter
/// appearing to stay "stationary" while the colors move behind it.
/// * **With Keys**: By providing a [ValueKey], Flutter matches the [State]
/// to the [Widget] via the key rather than the index. When the list is
/// reversed, the [State] moves with the color.
///
/// To see the difference, find the `ColoredWidgetsList` widget inside the `map`
/// function and comment/uncomment the `key: ValueKey(color)` line.
///
/// ** See code in examples/api/lib/foundation/key/value_key.0.dart **
/// {@end-tool}
///
/// See also:
///
/// * [Widget.key], which discusses how widgets use keys.
/// * [ObjectKey], which uses the identity of an object as the key.
/// * [UniqueKey], which is a key that is only equal to itself.
class ValueKey<T> extends LocalKey {
/// Creates a key that delegates its [operator==] to the given value.
const ValueKey(this.value);
/// The value to which this key delegates its [operator==].
final T value;
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
}
return other is ValueKey<T> && other.value == value;
}
@override
int get hashCode => Object.hash(runtimeType, value);
@override
String toString() {
final valueString = T == String ? "<'$value'>" : '<$value>';
if (runtimeType == ValueKey<T>) {
return '[$valueString]';
}
return '[$T $valueString]';
}
}