在 Flutter 中,⼀切的显示都是 Widget 。Widget 是⼀切的基础,作为响应式的渲染,类似 MVVM 的实现机制。
import 'package:flutter/material.dart';
void main() {
/// runApp 是widget树中的根节点
/// Widget 树有两个 widgets,Center及其子widget -- Text
runApp(
const Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
),
),
);
}
我们可以通过修改数据,再⽤ setState 设置数据,Flutter 会⾃动通过绑定的数据更新 Widget 。 所以你需要做的就是实现 Widget 界⾯,并且和数据绑定起来。
Widget 分为 有状态(StatefulWidget) 和 ⽆状态(StatelessWidget) 两种,在 Flutter 中每个⻚⾯都是⼀帧,⽆状态就是保持在那⼀帧,⽽有状态的 Widget 当数据更新时,其实是绘制了新的 Widget,只是 State 实现了跨帧的数据同步保存。
-
StatelessWidget⽆状态 widget 接收的参数来自于它的父 widget,它们储存在
final成员变量中。当 widget 需要被build()时,就是用这些存储的变量为创建的 widget 生成新的参数。 -
StatefulWidget有状态 是一种特殊的 widget,它会生成 State 对象,用于保存状态。在 State 中,你可以动态改变数据,这类似 MVVM 实现,在 setState 之后,改变的数据会触发 Widget 重新构建刷新。
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
)));
}
class TextColumn1 extends StatelessWidget {
final String? name;
const TextColumn1({this.name, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
String defaultName = name ?? 'herry';
return Text.rich(TextSpan(text: 'Hello ', children: <TextSpan>[
TextSpan(
text: '$defaultName ',
style: const TextStyle(color: Colors.green),
),
const TextSpan(
text: 'beautiful ', style: TextStyle(fontStyle: FontStyle.italic)),
const TextSpan(
text: 'world ', style: TextStyle(fontWeight: FontWeight.bold))
]));
}
}
class CounterDisplay extends StatelessWidget {
final int count;
const CounterDisplay({required this.count, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text('Count:$count');
}
}
class CounterIncrementer extends StatelessWidget {
final VoidCallback onPressed;
const CounterIncrementer({required this.onPressed, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(onPressed: onPressed, child: const Text('Increment'));
}
}
class Counter extends StatefulWidget {
const Counter({Key? key}) : super(key: key);
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _increment() {
setState(() {
++_counter;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CounterIncrementer(onPressed: _increment),
const SizedBox(
width: 18,
),
CounterDisplay(count: _counter),
// const TextColumn1(), // 输出 herry
const TextColumn1(name: 'mickey'), // 输出 mickey
],
);
}
}
State 中主要的声明周期有 :
- initState :初始化,理论上只初始化⼀次。
- didChangeDependencies:在 initState 之后调⽤,此时可以获取其他 State 。
- dispose :销毁,只会调⽤⼀次。