DartNotes
A shorthand => (arrow) syntax
- contain a single statement(一条语句)
- especially useful when passing anonymous functions as arguments
1
flybyObjects.where((name) => name.contains('turn')).forEach(print);
箭头函数:
- forEach
1
2
3
4
5
6
7 List l1 = [1, 2];
l1.forEach((item) {
print(item);
});
l1.forEach((item) => print(item));
- map
1
2
3
4
5
6
7 var l2 = l1.map((item) {
return item % 2 == 0 ? item * 2 : item;
});
print(l2.toList());
var l3 = l1.map((item) => item % 2 == 0 ? item * 2 : item);
print(l3);
检查Null或零
- 只有bool值为“true”才被视为true;
?.
:运算符在左边为null的情况下会阻断右边的调用;??
:在左边表达式为null时为其设置默认值;searchModel?.data?.length ?? 0
:获取一个对象中数组长度
const
- 类是对象的模板,对象是类的实例
static
: 所修饰的变量是属于类的,而不是属于对象的; static变量直到运行期被使用时才会实例化const
:
const 定义时,需要是个明确的值,不能像 final 那样,运行时才知道是什么值;
被const修饰的对象有些特殊的属性和限制:
①必须依靠编译期间就能够计算出来的数据进行创建,包括两种情况:
1)使用Dart内置数据类型的值(int double bool String List Map等等)进行赋值,或者使用内置数据类型的字面量通过基本运算得到的值,而不能依赖运行期计算出来的值,但是new DateTime.now()不行
2)const构造函数创建的对象这里的Student类中定义了一个const构造函数,一个类能够定义 const 构造函数的前提是成员变量必须都是用final或const修饰的
②const导致的不可变性是可传递的
③相同的const变量不会在内存中重复创建,如果表达式被调用了多次,则重用之前创建好的常量,或者用代码表达这一特性1
2
3
4
5
6
7getConst() => const [1, 2];
main() {
var a = getConst();
var b = getConst();
identical(a, b); // =>true
}
//identical用于检查两个引用是否指向同一个对象。
super
1 | class Person { |
key
Keys preserve state when widgets move around in your widget tree. They can be used to preserve the user’s scroll location, or keeping state when modifying a collection. 当组件在组件树中移动时使用Key可以保持组件之前的状态,比如在用户滑动时或者集合改变时。
当使用Stateless Widget时,我们并不需要使用key,当使用Stateful Widget时,集合内有数据移动和改变并且需要展示到界面时才需要key
//TODO
BuildContext
BuildContext objects are actually Element objects. The BuildContext interface is used to discourage direct manipulation of Element objects.
视图树装载过程
StatelessWidget
- 首先它会调用StatelessWidget的 createElement 方法,并根据这个widget生成StatelessElement对象。
- 将这个StatelessElement对象挂载到element树上。
- StatelessElement对象调用widget的build方法,并将element自身作为BuildContext传入。
StatefulWidget
- 首先同样也是调用StatefulWidget的 createElement方法,并根据这个widget生成StatefulElement对象,并保留widget引用。
- 将这个StatefulElement挂载到Element树上。
- 根据widget的 createState 方法创建State。
- StatefulElement对象调用state的build方法,并将element自身作为BuildContext传入。
所以我们在build函数中所使用的context,正是当前widget所创建的Element对象。
of(context)方法
1 | //打开一个新的页面 |
以Navigator打开新页面为例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24static NavigatorState of(
BuildContext context, {
bool rootNavigator = false,
bool nullOk = false,
}) {
//关键代码-----------------------------------------v
final NavigatorState navigator = rootNavigator
? context.rootAncestorStateOfType(const TypeMatcher<NavigatorState>())
: context.ancestorStateOfType(const TypeMatcher<NavigatorState>());
//关键代码----------------------------------------^
assert(() {
if (navigator == null && !nullOk) {
throw FlutterError(
'Navigator operation requested with a context that does not include a Navigator.\n'
'The context used to push or pop routes from the Navigator must be that of a '
'widget that is a descendant of a Navigator widget.'
);
}
return true;
}());
return navigator;
}
可以看到,关键代码部分通过context.rootAncestorStateOfType
向上遍历 Element tree,并找到最近匹配的 NavigatorState
。也就是说of实际上是对context跨组件获取数据的一个封装。
而我们的Navigator的 push操作就是通过找到的 NavigatorState
来完成的。
需要注意的是,在 State 中 initState
阶段是无法跨组件拿数据的,只有在didChangeDependencies
之后才可以使用这些方法.
WidgetsFlutterBinding
Mixins
Mixin 能够更好的解决多继承中容易出现的问题,如:方法优先顺序混乱、参数冲突、类结构变得复杂化等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
46class A {
a() {
print("A.a()");
}
b() {
print("A.b()");
}
}
class A2 {
a() {
print("A2.a()");
}
}
class B {
a() {
print("B.a()");
}
b() {
print("B.b()");
}
c() {
print("B.c()");
}
}
class G extends B with A, A2 {
}
testMixins() {
G t = new G();
t.a();
t.b();
t.c();
}
/// ***********************输出***********************
///I/flutter (13627): A2.a()
///I/flutter (13627): A.b()
///I/flutter (13627): B.c()
在 Dart 中 with 就是用于 mixins。
可以看出,class G extends B with A, A2
,在执行 G 的 a、b、c 方法后,输出了 A2.a()、A.b() 、B.c()
所以结论上简单来说,就是相同方法被覆盖了,并且 with
后面的会覆盖前面的。
1 |
|
A、A2、B中的所有方法都被执行了,且只执行了一次,同时执行的顺序也是和 with 的顺序有关
如果把上方代码中 class A.a()
方法的 super 去掉,那么你将看不到 B.a() 和 base a() 的输出。
WidgetsFlutterBinding
在 Flutter启动时runApp会被调用,作为App的入口,它肯定需要承担各类的初始化以及功能配置,这种情况下,Mixins 的作用就体现出来了。
map
1 | return Column( |
1 | return Column( |
###.. Operator1
2
3
4
5
6
7StringBuffer valueBuffer = new StringBuffer();
valueBuffer..write("I")
..write(" ")
..write("love")
..write(" ")
..write("Flutter");
print(valueBuffer.toString());