Flutter Gallery 开发案例01——项目初始化

概述

       当今的科技圈,发展日新月异,新技术层出不穷,前端开发涌现出了 NodeJS, ReactJS, React Native 等等的全新技术。谷歌作为全球技术的领导者之一,也在不断的推出各种各样的新技术。Flutter 就是谷歌在2017年年底才正式公开的一项全新的开发技术平台。对于这门技术具体的介绍和功能,请参考 https://flutter.io 或者国内志愿者进行翻译的中文网站 http://doc.flutter-dev.cn/。简而言之,Flutter 的出现是为了加速移动端应用的开发效率,而运用的方式则是,Flutter 选择 Dart 作为开发语言,在编译阶段,直接将代码编译为 Android 平台的本地代码以及 IOS 平台的原生代码。这样一来,开发者只需要维护一套代码,就可以得到 Android 和 IOS 平台的2个具有原生应用体验的 APP,大幅度的为移动应用开发加速。

       宏观的就说这么多,感兴趣的同学自行去了解,我的目的还是对想要了解 Flutter 开发流程的同学介绍在 Flutter 中一些最基本的控件和调试的方法。另外,对于想要询问 Flutter 目前是否适合用来做企业或者产品的移动应用开发的。我个人的答案是,目前不适合,Flutter 目前公开的版本仍然还是 beta 测试版本,距离 SDK 稳定还有很长的路要走。因此,目前的 Flutter 技术,我个人的看法是可以作为一个程序员额外的兴趣,如果你对这门新技术有兴趣,那么就和笔者一起来探索吧。如果你想快速的选择一门合适的语言用在生产环境,那么可能笔者的这个系列并不很适合。

       闲言少叙,书归正传。之所以选择 Flutter Gallery 这个项目作为开端,是笔者认为,这个项目的用户体验很不错,在代码层面,也包含了基本常用的各种控件以及 Flutter 开发的独特风格。

获取源代码

       这个系列的源代码笔者都托管在 https://gitee.com/foxchan/flutter_gallery上,具体的项目初始化请参考 gitee 主页。整个系列的代码笔者将使用一种分步骤分模块的方式进行安排,便于浏览的同学按照自己的学习进度循序渐进的阅读代码,更容易了解项目开发的全过程。一切就绪之后,打开终端,运行:

git clone https://gitee.com/foxchan/flutter_gallery.git

将项目克隆到本地。当然,对于我们这个系列,笔者还是更鼓励大家跟随笔者一起,从0开始手敲代码,笔者提供的代码仅仅作为各位的参考。下面,就开始本篇文章的学习内容,在这片文章中,我将带着大家新建一个 Flutter 项目,并且在模拟器上把新建的这个项目运行起来。

创建项目

       笔者所使用的IDE为VSCode,当然,你可以选择任何一款你用的顺手的IDE进行编程,这都不影响。具体的各种IDE的配置,请参考 https://flutter.io/get-started/editor/#androidstudio 或者 http://doc.flutter-dev.cn/get-started/editor/ 。

安装插件

Flutter 已经为 VSCode 开发了便于开发的插件,这里笔者简单的提一下,我们要安装 dart code 插件,

当然,为了更好的开发体验,笔者也安装了 Flutter Snippets 这个插件。

新建项目

接下来,我们就可以在 VSCode 中,使用 Flutter 为我们提供的插件,创建咱们的第一个项目了。打开 VSCode 的命令执行面板,输入'flutter',

选择'Flutter: New Project',接下来会提示输入项目的名称,这里,我们第一个子项目的目的很简单,就是环境的搭建,因此我们输入'sec01_setup',回车以后,VSCode 会为我们把基本的项目结构生成。至此,我们目前的文件结构如下图:

扫描二维码关注公众号,回复: 120107 查看本文章

接下来的工作,我们需要在 /sec01_setup 目录中来完成,在 VSCode 中,打开 /sec01_setup,目前我们的项目结构如下,

接下来,我们简单的来了解一下这个最简单的 Flutter 项目的构造,首先我们要关注到的是 pubspec.yaml 这个文件。这个文件就是 Flutter 项目的配置文件,他的作用就是为项目提供各种资源和项目的信息。

name: sec01_setup
description: A new Flutter project.

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter

删除以 '#' 开头的注释文件以后,我们得到了上面这个最精简的配置文件,基本上都一目了然,其中有项目名称,项目的描述信息以及项目中的依赖。

按F5运行项目之后,我们就能看到这第一个最简单的项目的情况了,如下图所示:

可以看到,这个项目运行之后,是一个很简单的统计按钮点击次数的应用,点击右下角的加号按钮,屏幕中央的数字就加1。接下来我们就先来分析一下这个项目的构成,了解一下 Flutter 应用的基本结构。

       Flutter 应用的应用入口还是众所周知的 main 函数,如下:

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

这个就是整个应用程序的入口,runApp 中有一个参数,类型为 Widget,这个可以理解为应用的入口控件。另外,有一点需要注意的是,不像 Android 或者 IOS 框架,在 Flutter 中,几乎所有的结构都是 Widget,也就是组件,因此,在 main 程序中就直接加载了 MyApp 这个 Widget。

       继续分析,看到 MyApp 这个类,继承自 StatelessWidget,顾名思义,这是一个无状态的控件。如何理解无状态?也就是说,MyApp 这个控件的作用只有一个,那就是根据目前具有的参数,绘制相应的控件,不对用户输入或者网络等进行处理。对于一个 Widget 来说,最重要的方法就是 build,看下面的代码:

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'),
    );
  }
}

build 方法会在控件重绘的时候被调用。这段代码就是 MyApp 中的绘制部分,可以看到,这里返回了 MaterialApp 控件,这里需要注意,在 Flutter 应用中,runApp 中调用的控件必须基于 MaterialApp,否则会报错。这里,我们着重关注的参数是 home 这个参数,这代表应用程序启动以后,MyHomePage 这个控件将会被最先调用。

       接下来我们就来看看 MyHomePage 又是一个什么样的控件。

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

  final String title;

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

如上,这个控件继承自 StatefulWidget 这个父类,顾名思义,这就是一个有状态的控件。按照上文的理解,在这个控件中,我们将处理来自系统,用户或者网络的各项事件。在 Flutter 开发中,我们需要在 StatefulWidget 的子类中重写 createState() 方法,返回我们自定义的处理事件的 State 对象,我们马上就会讲到。

      可以看到,我们在 createState() 方法中返回了一个 State 控件,_MyHomePageState。在开始看代码之前,我们提一个 Dart 中的小细节,注意 _MyHomePageState 这个类的类名以下划线开始,这代表了 _MyHomePageState 这个类为私有类,相当于 Java 中的 private class MyHomePageState。下面我们来剖析一下这个类的具体实现:

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

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  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.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ),
    );
  }
}

在 State 的实现类中,最为关键的方法就是 setState() 调用这个方法之后,控件的状态就会被标记为已改变,涉及到的 Widget 就会被要求进行重绘,Widget 的 build 方法就会被调用。我们来看这个 State 控件中的 build 方法,首先,build 方法返回了一个根控件 Scaffold,这个控件是一个 Flutter 中作为 Material Design 风格的一个基础控件,调用这个控件之后,会生成一个 Material Design 的基本框架,在上图的手机截图中也能看出来。继续看,在 Scaffold 控件的 body 参数中,就是项目的主体部分了。项目的主体部分结构如下:Center -> Column -> [Text, Text]。在 Flutter 的控件布局中,官方提倡的是组合的方式,因此一般情况下,一个控件就代表一种布局效果。这种风格在之后的教程中还会经常看到,这里先提一句。我们来分析一波,在 AppBar 下面,首先放置了一个 Center 控件,这个控件会将其中的子控件进行居中处理。其中嵌套了一个 Column 控件,这个控件是一个列式布局的控件,即所有的控件在垂直方向上依次分布,每个控件一行。

       接着,我们来关注一下 Column 控件中的第二个 Text 控件,这个控件就是显示按钮点击次数的控件,根据用户点击次数的变化,显示对应的数字。可以看到,在这个控件中,设置了显示内容为 _counter 变量中的值。

       最后,在 FloatingActionButton 中,绑定了按钮的点击事件。至此,整个基本项目的流程和 Flutter 程序的基本运行流程就梳理通畅了。

猜你喜欢

转载自my.oschina.net/u/554627/blog/1799200