用Android Studio和VS Code创建的Flutter应用模板默认是一个简单的计数器示例。
运行新建的Demo,运行之后的效果图如下:
在这个Demo里,每次点击图中的“+”号,中间的数字就会自动+1
代码在lib文件夹下面的main.dart
import 'package:flutter/material.dart';void main() { runApp(MyApp());}class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); }}class MyHomePage extends StatefulWidget { MyHomePage({Key key, 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: [ 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), ), ); }}
分析
导入包。
import 'package:flutter/material.dart';
此行代码作用是导入了Material UI组件库。Material是一种标准的移动端和web端的视觉设计语言, Flutter默认提供了一套丰富的Material风格的UI组件。
应用入口。
void main() => runApp(MyApp());
与C/C++、Java类似,Flutter 应用中
main
函数为应用程序的入口。main
函数中调用了runApp
方法,它的功能是启动Flutter应用。runApp
它接受一个Widget
参数,在本示例中它是一个MyApp
对象,MyApp()
是Flutter应用的根组件。main
函数使用了(=>
)符号,这是Dart中单行函数或方法的简写。
应用结构。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
//应用名称
title: 'Flutter Demo',
theme: new ThemeData(
//蓝色主题
primarySwatch: Colors.blue,
),
//应用首页路由
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
MyApp
类代表Flutter应用,它继承了StatelessWidget
类,这也就意味着应用本身也是一个widget。在Flutter中,大多数东西都是widget(后同“组件”或“部件”),包括对齐(alignment)、填充(padding)和布局(layout)等,它们都是以widget的形式提供。
Flutter在构建页面时,会调用组件的
build
方法,widget的主要工作是提供一个build()方法来描述如何构建UI界面(通常是通过组合、拼装其它基础widget)。MaterialApp
是Material库中提供的Flutter APP框架,通过它可以设置应用的名称、主题、语言、首页及路由列表等。MaterialApp
也是一个widget。home
为Flutter应用的首页,它也是一个widget。
首页
class MyHomePage extends StatefulWidget { MyHomePage({Key key, 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: [ 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), ), ); }
MyHomePage
是Flutter应用的首页,它继承自StatefulWidget
类,表示它是一个有状态的组件(Stateful widget)。有状态的组件(Stateful widget) 和无状态的组件(Stateless widget)有两点不同:
Stateful widget可以拥有状态,这些状态在widget生命周期中是可以变的,而Stateless widget是不可变的。
Stateful widget至少由两个类组成:
_MyHomePageState
类是MyHomePage
类对应的状态类。
一个
StatefulWidget
类。一个
State
类;StatefulWidget
类本身是不变的,但是State
类中持有的状态在widget生命周期中可能会发生变化。
State类
接下来,我们看看_MyHomePageState
中都包含哪些东西:
该组件的状态。由于我们只需要维护一个点击次数计数器,所以定义一个
_counter
状态:int _counter = 0; //用于记录按钮点击的总次数
_counter
为保存屏幕右下角带“+”号按钮点击次数的状态。设置状态的自增函数。
void _incrementCounter() {
setState(() {
_counter++;
});
}当按钮点击时,会调用此函数,该函数的作用是先自增
_counter
,然后调用setState
方法。setState
方法的作用是通知Flutter框架,有状态发生了改变,Flutter框架收到通知后,会执行build
方法来根据新的状态重新构建界面, Flutter 对此方法做了优化,使重新执行变的很快,所以你可以重新构建任何需要更新的东西,而无需分别去修改各个widget。构建UI界面
构建UI界面的逻辑在
build
方法中,当MyHomePage
第一次创建时,_MyHomePageState
类会被创建,当初始化完成后,Flutter框架会调用Widget的build
方法来构建widget树,最终将widget树渲染到设备屏幕上。所以,我们看看_MyHomePageState
的build
方法中都干了什么事:Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'You have pushed the button this many times:',
),
new Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
);
}
Scaffold
是 Material 库中提供的页面脚手架,它提供了默认的导航栏、标题和包含主屏幕widget树(后同“组件树”或“部件树”)的body
属性,组件树可以很复杂。body
的组件树中包含了一个Center
组件,Center
可以将其子组件树对齐到屏幕中心。此例中,Center
子组件是一个Column
组件,Column
的作用是将其所有子组件沿屏幕垂直方向依次排列;此例中Column
子组件是两个Text
,第一个Text
显示固定文本 “You have pushed the button this many times:”,第二个Text
显示_counter
状态的数值。floatingActionButton
是页面右下角的带“+”的悬浮按钮,它的onPressed
属性接受一个回调函数,代表它被点击后的处理器,本例中直接将_incrementCounter
方法作为其处理函数。
现在,我们将整个计数器执行流程串起来:当右下角的floatingActionButton
按钮被点击之后,会调用_incrementCounter
方法。在_incrementCounter
方法中,首先会自增_counter
计数器(状态),然后setState
会通知Flutter框架状态发生变化,接着,Flutter框架会调用build
方法以新的状态重新构建UI,最终显示在设备屏幕上。