工程目录介绍
代码介绍
示例代码在 mian.dart 这个文件中,将代码折叠可以发现,除了main函数,还有三个class
main函数:
void main() {
runApp(const MyApp());
}
只调用了一个函数runApp,runApp是一个flutter App的入口函数
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
示例中runApp中传入了一个MyApp示例
MyApp Class:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
Flutter 应用为 MyApp 类的一个实例,而 MyApp 类继承自 StatelessWidget 类,这也就意味着应用本身也是一个 Widget。事实上,在 Flutter 中,Widget 是整个视图描述的基础,在 Flutter 的世界里,包括应用、视图、视图控制器、布局等在内的概念,都建立在 Widget 之上,Flutter 的核心设计思想便是一切皆 Widget。
查看MyApp类的代码
const MyApp({Key? key}) : super(key: key);
这是一个构造函数!!!
构造函数下面是一个build方法
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
Widget 是组件视觉效果的封装,是 UI 界面的载体,因此我们还需要为它提供一个方法,来告诉 Flutter 框架如何构建 UI 界面,这个方法就是 build。
在 build 方法中,我们通常通过对基础 Widget 进行相应的 UI 配置,或是组合各类基础 Widget 的方式进行 UI 的定制化。比如在 MyApp 中,我通过 MaterialApp 这个 Flutter App 框架设置了应用首页,即 MyHomePage。当然,MaterialApp 也是一个 Widget。
class MaterialApp extends StatefulWidget {***}
MaterialApp 类是对构建 material 设计风格应用的组件封装框架,里面还有很多可配置的属性,比如应用主题、应用名称、语言标识符、组件路由等,这里我们主要关注home属性,表示因应用的home页。
MyHomePage Class
MyHomePage 是应用的首页,继承自 StatefulWidget 类。
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
MyHomePage 类也是 Widget,但与 MyApp 类不同的是,它并没有一个 build 方法去返回 Widget,而是多了一个 createState 方法返回 _MyHomePageState 对象,而 build 方法则包含在这个 _MyHomePageState 类当中,原因就是MyHomePage继承自StatefulWidget而MyApp继承自StatelessWidget。
StatelessWidget 与 StatefulWidget
StatelessWidget :无状态Widget
实现: 在需要实现一个StatelessWidget组件的时候,声明一个class类需要通过extends继承StatelessWidget,然后实现build方法,就可以创建一个无状态的Widget。这个Widget创建完成后,Widget的状态就固定了,当前Widget就是一个无状态的,当前Widget 的内容固定,不可更改。
注意: 如果无状态Widget里面有子Widget,并且子Widget是有状态的,则子Widget的内容是可以通过setState来更改的。无状态Widget影响的仅仅是自己是无状态的,不回影响他的父Widget和子Widget。
StatefulWidget 有状态Widget
实现: StatefulWidget组件的实现相对于StatelessWidget来说,复杂那么一点点。首先也是要通过extends继承StatefulWidget,然后实现State createState()函数,实现createState的过程中,可以通过State来集成一个有状态的Widget。状态的更改一定要配合使用 setState。通过这个方法的调用,Flutter 会在底层标记 Widget 的状态,随后触发重建。
_MyHomePageState 类
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
由于源代码内部有很多布局相关代码,为了便于学习理解,这里将它缩减后代码如下:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() => setState(() {_counter++;});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(Widget.title)),
body: Text('You have pushed the button this many times:$_counter')),
floatingActionButton: FloatingActionButton(onPressed: _incrementCounter)
);
}
_MyHomePageState 中创建的 Widget Scaffold,是 Material 库中提供的页面布局结构,它包含 AppBar、Body,以及 FloatingActionButton。
- AppBar 是页面的导航栏,我们直接将 MyHomePage 中的 title 属性作为标题使用。
- body 则是一个 Text 组件,显示了一个根据 _counter 属性可变的文本:‘You have pushed the button this many times:$_counter’。
- floatingActionButton,则是页面右下角的带“+”的悬浮按钮。我们将 _incrementCounter 作为其点击处理函数。
_incrementCounter 的实现很简单,使用 setState 方法去自增状态属性 _counter。setState 方法是 Flutter 以数据驱动视图更新的关键函数,它会通知 Flutter 框架:我这儿有状态发生了改变,赶紧给我刷新界面吧。而 Flutter 框架收到通知后,会执行 Widget 的 build 方法,根据新的状态重新构建界面。
void _incrementCounter() {
setState(() {
_counter++;
});
}
整个流而成如下:
|