入门Flutter第一步——计数器示例源码分析(超详细)

在Windows上搭建Flutter开发环境,并在模拟器上看到myapp中创建的 Flutter 应用,其中会有一个计数器示例的应用模板。

刚开始学习 Flutter 时,在开始编写第一个 Flutter App 前,起码还是需要先完全看懂这块基础的示例代码。
代码如下(对其英文注释进行了一下中文翻译):

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // 这个 Widget 是应用程序的根.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // 这是应用程序的主题。
        //
        // 试着用“flutter run”运行你的应用程序,你将看到应用程序有一个蓝色的工具栏
        // 然后,在不退出应用的情况下, 尝试改变下面 primarySwatch 的颜色为绿色 Colors.green
        // 然后调用“热重载”(在你运行“flutter run”的控制台中按“r”,或简单地保存你的修改到“热重载”中的 Flutter IDE)
        // 注意,计数器没有重置为零;应用程序没有重新启动
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  //这个 Widget 是你的应用程序主页. 它是有状态的, 表示它具有一个 State 对象 (定义如下),该对象包含影响其外观的字段。

  // 这个类是状态的配置. 它保存由父组件(本例中为App Widget)提供的值(本例中为标题),并由 State 的 build 方法使用。
  // Widget子类中的字段始终标记为"final".
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // 调用 setState 告诉 Flutter 框架 State 已发生更改
      // 这会导致它重新运行下面的构建方法,以便显示更新的值
      // 如果我们在不调用setState()的情况下更改了_counter,那么构建方法就不会再次被调用,因此什么也不会发生
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // 每次调用setState时都会重新运行该方法, 例如上面的_incrementCounter方法所做的.
    //
    //Flutter框架已经过优化,可以快速重新运行构建方法,因此您可以重建任何需要更新的内容,而不必单独更改 Widget 的实例。
    return Scaffold(
      appBar: AppBar(
        // 在这里,我们从由App.build方法创建的MyHomePage对象中获取值,并使用它来设置我们的应用栏标题。
        title: Text(widget.title),
      ),
      body: Center(
        //Center是一个布局 Widget
        //它接受一个子元素并将其放置在父元素中
        child: Column(
          // Column也是一个布局widget. 它采用一列子元素并将它们垂直排列
          // 默认情况下, 它会自行调整大小以使其子元素水平放置,并尝试与父级一样高。
          //
          // 调用 "debug painting" (在控制台中按“p”, 在 Android Studio 中的 Flutter Inspector 选择 "Toggle Debug Paint"操作)
          // 查看每个 widget 的线框
          //
          // 列具有各种属性来控制其自身大小以及子元素的位置
          // 这里我们使用mainAxisAlignment将子元素垂直居中;
          // 这里的主轴是垂直轴,因为列是垂直的(交叉轴是水平的)。
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // 该结尾逗号使自动格式化的构建方法更好.
    );
  }
}

1.最开始第一行代码导入了 Material UI 组件库
Material是一种标准的移动端和web端的视觉设计语言, Flutter 默认提供了一套丰富的 Materia l风格的 UI 组件

2.main 函数为应用程序的入口

  • main 函数中调用了 runApp 方法,接受一个 Widget 并使其成为widget树的根(框架强制根widget覆盖整个屏幕),功能是启动 Flutter 应用。(在此示例中它是一个 MyApp 对象,MyApp() 是 Flutter 应用的根组件。)
  • main 函数使用了(=>)符号,这是 Dart 中单行函数或方法的简写

3.MyApp继承了 StatelessWidget类,这将会使应用本身成为一个Stateless widgets(无状态组件可以理解为将外部传入的数据转化为界面展示的内容,只会渲染一次)

  • 在Flutter中,大多数东西都是widget,包括对齐(alignment)、填充(padding)和布局(layout),它们都是以widget的形式提供。
  • widget的主要工作是实现一个build()函数用以构建自身。一个widget通常由一些较低级别widget组成,通过组合、拼装其它基础 widget。(Flutter 在构建页面时,会调用组件的 build 方法。类似于 React 中的 render 方法
  • MaterialApp 是一个 widget(由是Material库中提供的Flutter APP框架),通过它可以设置应用的名称、主题、语言、首页及路由列表等。

4.MyHomePage 是Flutter应用的首页,它继承自StatefulWidget类,表示是一个Stateful widgets(有状态组件是定义交互逻辑和业务数据,可以理解为具有动态可交互的内容界面,会根据数据的变化进行多次渲染)

  • 这个类里的第一行,是生成构造函数。当前构造函数冒号 (:) 之后,声明调用父类构造函数(父类的构造函数参数在构造函数执行之前执行)
  • 这个 key 属性类似于 React/Vue 中的 key,主要的作用是决定是否在下一次 build 时复用旧的 widget
  • 实现一个 stateful widget 至少需要两个类:
    一个 StatefulWidget类:StatefulWidget类本身是不变的
    一个 State类: State类在widget生命周期中始终存在

5._MyHomePageState 类是 MyHomePage 类对应的状态类,该类持有 MyHomePage widget 的状态。
(以下划线(_)开头,在Dart语言中使用下划线前缀标识符,会强制其变成私有的)

  • _counter 该组件的状态
  • _incrementCounter 该组件更新状态的自增函数
  • Scaffold 是 Material 库中提供的页面脚手架,它提供了默认的导航栏、标题和包含主屏幕widget树
  • 剩下的也只是一些组件的属性、函数及事件处理的调用

这里是对 Flutter生命周期 的一点梳理。

学习链接:
Flutter中文网
《Flutter实战》(计数器应用示例)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342