共计 2861 个字符,预计需要花费 8 分钟才能阅读完成。
???? 0
咱们所做进去的 App,不能仅仅是一幅静止不动的画面!想一下你生存中的这些场景:
- 手机衰弱 App 上的步数随着你的幸(huang)苦(dong)运(shou)动(bi)而减少;
- 手机时钟 App 里的秒表计数随着工夫的飞快流逝而扭转;
- 进度条缓缓延长;
如果这些 App 是用 Flutter 编写成的,那么这些 Widget 的 “状态” 就在随着用户的操作而产生扭转。
StatefulWidget
就是有状态的Widget
。它在程序运行时,状态被容许产生扭转。
只有状态可能产生扭转的 StatefulWidget
能力让页面不再变化无穷。也就是说,要想编写出 可能被用户操作 的 App,就必须要应用StatefulWidget
。
???? 目录
- ???? Here’s the code!
- ???? 了解
StatefulWidget
和State
- ???? 当咱们
setState(() {});
时,Flutter 在幕后帮咱们做了什么?
???? 1
Here’s the code!
咱们要实现这样的一个计数器:
咱们实现了一个简略的计数器,画面两头的数字随着咱们按动左下角的蓝色按钮而递增。
main.dart
如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() {return MyAppState();
}
}
class MyAppState extends State<MyApp> {
var _counter = 0;
@override
Widget build(BuildContext buildContext) {
return MaterialApp(
title: '计数器',
home: Scaffold(
appBar: AppBar(title: Text('计数器')
),
body: Center(
child: Text(
'$_counter',
style: TextStyle(fontSize: 30)
)
),
floatingActionButton: FloatingActionButton(onPressed: () => setState(() => _counter += 1),
child: Icon(Icons.add)
),
)
);
}
}
代码来得太快,就像龙卷风?不要胆怯,让咱们一点一点分析它。
???? 2
了解 StatefulWidget
和State
结尾,我引入了package:flutter/material.dart
,这外面蕴含了 Flutter 曾经封装好的 Material 格调的Widget
。
import 'package: flutter/material.dart'
接下来,是经典的runApp()
,这个时候把我编写好的MyApp
(继承了StatefulWidget
)的实例作为参数传入。
void main() => runApp(MyApp());
而后在 MyApp
内,咱们会发现显示的具体内容 并不是在这个类外面实现的!
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() {return MyAppState();
}
}
在这个类外面,咱们重写了一个 createState()
函数,而后这个函数返回了一个 State<MyApp>
,是用户定义的MyAppState
类的实例!
而后 MyAppState
是何方神圣呢?
class MyAppState extends State<MyApp> {
var _counter = 0;
@override
Widget build(BuildContext buildContext) {
return MaterialApp(
title: '计数器',
home: Scaffold(
appBar: AppBar(title: Text('计数器')
),
body: Center(
child: Text(
'$_counter',
style: TextStyle(fontSize: 30)
)
),
floatingActionButton: FloatingActionButton(onPressed: () => setState(() => _counter += 1),
child: Icon(Icons.add)
),
)
);
}
}
能够看到了,MyAppState
继承了 State<MyApp>
,而在这个类外面,咱们重写了build()
函数,并将这个 Widget
的内容写在了这外面。
所以,咱们能够得悉:
StatefulWidget
外面须要重写createState()
函数,这个函数返回一个State<StatefulWidget>
的实例。State<StatefulWidget>
外面须要重写build()
函数,这个函数返回一个Widget
的实例。
然而,咱们会发现,仅仅满足了这些,Widget
的状态还不足以发生变化。回看方才的源码,这里有一行:
onPressed: () => setState(() => _counter += 1)
floatingActionButton
的 onPressed
属性定义了这个按钮按完之后会触发什么动作,它的值是一个函数(在 Dart 内,函数是一等对象)。这个函数它会执行 setState(() => _counter += 1)
。那么,这个setState()
是做什么的呢?
???? 3
当咱们 setState(() {});
时,Flutter 在幕后帮咱们做了什么?
setState(fn)
会先执行咱们传入的函数fn
。- 接下来,
setState()
会将这个组件标记为“脏的”。 - 下一帧时,Flutter 会从新执行这个“脏”组件的
build()
函数,将它从新渲染一遍。
在上述计数器程序中
setState(fn);
的执行过程。动图为自制,转载请注明出处。图中组件树为了简洁明了,省略了AppBar
和Icon
等Widget
,只注明参加了这个过程的少数几个Widget
也就是说,setState({} ());
才是本程序的点睛之笔。
???? -1
总结
StatefulWidget
就是有状态的Widget
。它在程序运行时,状态被容许产生扭转,要想编写出 可能被用户操作 的 App,就必须要应用StatefulWidget
。- 咱们实现了一个简略的计数器。
StatefulWidget
外面须要重写createState()
函数,这个函数返回一个State<StatefulWidget>
的实例。State<StatefulWidget>
外面须要重写build()
函数,这个函数返回一个Widget
的实例。-
当咱们执行
setState(fn);
时:setState(fn)
会先执行咱们传入的函数fn
。- 接下来,
setState()
会将这个组件标记为“脏的”。 - 下一帧时,Flutter 会从新执行这个“脏”组件的
build()
函数,将它从新渲染一遍。
它的用处是刷新一个组件的 状态。