本系列文章主要整理Flutter的知识汇总,由浅入深,从Widget的搭建到其中的原理。本文还是围绕Widget在开发中应用和理解。
关于Flutter环境配置和首次创建可以参考前面文章。链接如下:
Flutter 使用AndroidStudio并集成Flutter界面
书接上一篇:Flutter Widget:StatefulWidget & StatelessWidget-CSDN博客
创建Flutter应用模板项目
通过 Android Studio 或 VS Code 创建一个新的 Flutter 工程,命名为 "first_flutter_app"。创建好后,就会得到一个默认的计数器应用示例。运行创建的工程,如下图所示:
在 lib/main.dart 文件中源码如下:
Dart
import 'package:flutter/material.dart';//导入了 Material UI 组件库
void main() => runApp(MyApp());//入口
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',//应用标题
theme: ThemeData(primarySwatch: Colors.blue,),//主题色
home: MyHomePage(title: 'Flutter Demo Home Page'),//应用首页路由
);}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _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>[
Text('You have pushed the button this many times:'),
Text('$_counter',style: Theme.of(context).textTheme.headline4,
),],),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,tooltip: 'Increment',child: Icon(Icons.add),
), );
}
}
MyApp
类
它表示一个Flutter 应用,继承自 StatelessWidget
类,意味着应用本身也是一个widget。
应用在构建页面时,会调用Widget的build
方法。该方法来描述如何构建 UI 界面。
在Flutter 中是通常是通过 Widget 嵌套 Widget 的方式来构建UI和进行事件处理的。所以,Flutter 中万物皆为Widget。
自定义MyHomePage
类
它是这个应用的首页,继承自StatefulWidget
类,表示它是一个状态可变的widget。
StatefulWidget 可以拥有状态,这些状态在 widget 生命周期中是可以变的,而 StatelessWidget 是不可变的。
两者关键区别是有没有一个 State
类。 StatefulWidget
类本身是不变的,但是State
类中持有的状态,在 widget 生命周期中可以发生变化。
自定义_MyHomePageState
类
它是MyHomePage
类对应的状态类,继承自State类。
看到这里,可能已经发现:MyHomePage
类并没有build
方法。而MyApp
和_MyHomePageState都有``build
方法。后面会详细解答为什么MyHomePage
类并没有build
方法?
构建UI界面的build
方法
前面也说过:应用在构建页面时,会调用Widget的build
方法。该方法来描述如何构建 UI 界面。
当MyHomePage
第一次创建时,_MyHomePageState
类也会被创建。当初始化完成后,Flutter框架会调用 widget 的build
方法来构建 widget 树,最终将 widget 树渲染到设备屏幕上。
Scaffold
它是 Material 库中提供的页面脚手架。它提供了导航栏、标题和body
属性。路由默认都是通过Scaffold
创建的。
body
组件树
此例中,Center
可以将其子组件树对齐到屏幕中心。其子组件Column
组件作用是将其所有子组件沿屏幕垂直方向依次排列;
在_MyHomePageState类中有一个点击按钮事件:floatingActionButton的onPressed。
Dart
void _incrementCounter() {
setState(() {
_counter++;
});
}
setState
方法
它的作用是通知 Flutter 框架状态发生了改变,Flutter 框架收到通知后,会执行 build
方法来根据新的状态重新构建widget树,更新UI界面。
为什么MyHomePage
类并没有build
方法?
这个问题理解为:为什么build方法放在 State中,而不是放在StatefulWidget中?
首先,StatefulWidget
是一个状态可变的widget,每次状态改变都会调用build
方法,而且状态是保存在 State 中的。
如果build方法不放在state中,那么build
方法和状态会被分别在两个类中。每次构建时读取状态将会很不方便。大概代码会变成下面这样:
Dart
Widget build(BuildContext context, State state){
...
}
这样就会将State的所有状态声明为公开。但是,状态设置为公开后将不再具有私密性,这就会导致对状态的修改将会变的不可控。
将build()
方法放在State中的话,构建过程不仅可以直接访问状态,而且也无需公开私有状态。 更加方便和稳定。
至此,会不会发现仍然会有些困惑。其实,要深刻理解widget的关键在于State类。下篇见。