65.9K
CodeProject 正在变化。 阅读更多。
Home

Flutter入门:教程1 基础

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (9投票s)

2018年7月4日

CPOL

8分钟阅读

viewsIcon

40523

downloadIcon

282

在本教程中,我将一步一步地指导您构建您的第一个 Flutter 应用。

引言

您好! 这就是我的架构师在每次开始每日站会时说的话。我时隔许久再次写文章,也是同样的开场白。这是我的一个缺点,因为我很久没有学到任何新东西或值得分享的东西了!这些年来,我一直厚颜无耻地从别人那里获取灵感,而贡献甚少。

我上次写文章是在 Xamarin(那时它们还是独立软件,未被微软收购)的时候,那时 Joseph Hill 先生慷慨地分享了一个免费许可证给我。虽然我用它编码了一段时间后,由于我主要专注于 Android 平台,我觉得 C# 的代码编写很麻烦,因为它在内部将代码编译成 Java,并且代码结构与 Java 类似(例如事件处理程序等),我从未感到自在。渐渐地,我失去了兴趣,彻底放弃了移动平台学习。

然而,最近我发现了一个由 Google 开发的非常棒的跨平台移动开发工具,那就是 Flutter,尽管它仍处于 Beta 阶段,但我相信它有着光明的未来。此外,开发语言是 Dart,我很庆幸它比其他语言更接近 C++/C#,更容易学习,而且它是开源且积极开发的。尽管 Xamarin 移动开发套件现在可以通过 VS2017 社区版 免费获得。

背景

我引用自这篇 链接,作者是 Wm Leler 先生:

引用
“Flutter 是唯一一个无需 JavaScript 桥即可提供响应式视图的移动 SDK,这一点本身就足以让 Flutter 引起兴趣并值得尝试,但 Flutter 还有更具革命性的东西,那就是它实现 Widget 的方式。”

这张图片摘自上面同一个链接,它会让你了解 Flutter 如何原生渲染应用程序。

为什么 Flutter 使用 Dart

为了避免重复,我将引用这篇 链接 的内容,作者是 Wm Leler 先生。

  • Dart 可以 AOT(Ahead Of Time,提前编译)为快速、可预测的原生代码,这使得几乎所有 Flutter 的内容都可以用 Dart 编写。这不仅使 Flutter 快速,而且几乎所有东西(包括所有 Widget)都可以进行自定义。
  • Dart 还可以 JIT(Just In Time,即时编译)以实现极快的开发周期和颠覆性的工作流程(包括 Flutter 流行的亚秒级有状态热重载)。
  • Dart 可以更容易地创建流畅的动画和过渡,以 60fps 运行。Dart 可以在没有锁的情况下进行对象分配和垃圾回收。并且像 JavaScript 一样,Dart 避免了抢占式调度和共享内存(因此也避免了锁)。由于 Flutter 应用被编译为原生代码,因此它们不需要在不同领域之间进行缓慢的桥接(例如 JavaScript 到原生)。它们的启动速度也快得多。
  • Dart 使 Flutter 能够避免需要像 JSX 或 XML 这样的单独的声明式布局语言,或单独的视觉界面构建器,因为 Dart 的声明式、编程性布局易于阅读和可视化。由于所有布局都用一种语言在一个地方完成,因此 Flutter 可以轻松地提供使其布局变得轻而易举的高级工具。
  • 开发者发现 Dart 特别容易学习,因为它具有静态语言和动态语言用户都熟悉的特性。

总之,让我们开始吧。我将尽快发布单独的教程来介绍 Dart 语言的技巧和窍门, 我已经发布了本系列的第一篇文章,请 点击这里 访问第一篇。构建这些教程所需的工具如下:

虽然您可以使用 Visual Studio Code 代替 Android Studio,但我建议安装 Android Studio,因为它现在包含可视化 Android SDK。从命令行安装 SDK 会比较困难。至少,对于初学者来说,绝对不行

Using the Code

我将在本教程中执行以下操作,我将只专注于 StatelessWidget

  • 任务#1:创建一个带有显示标题的 AppBar 的页面。
  • 任务#2:在页面中间放置一个 Raised Button,并在 onClick 时显示 Snackbar。
  • 任务#3:在底部栏放置带有图标的按钮,并响应点击。

一如既往,就像我的其他文章一样,我假设阅读本文的人是新手,我会一步一步地开始。

  1. 打开 Android Studio,像这样配置 Flutter 和 Dart SDK/插件。您需要点击 File->Settings 并选择 plugins 来打开此页面。

    如果您没有看到已安装的插件,请按 Browse repositories 按钮并搜索 Flutter 插件,它也会一并安装 Dart 插件。

  2. 现在创建一个新的 Flutter 项目,并将其命名为 'tutorial1',请注意项目名称始终是小写。按 next 设置包名,然后最终完成。

     

  3. 删除项目创建时生成的所有样板代码。您的 lib 文件夹下的 main.dart 文件应该看起来像这样:
    import 'package:flutter/material.dart';
    import 'package:tutorial1/myhomepage.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Flutter Tutorial #1'),
        );
      }
    }
    我来解释一下这段代码的含义。
    • Flutter/Dart 项目的入口点是 main(),所以我们使用简短的代码 for RunApp,并传递 MyApp 的对象。MyApp 作为我们教程的基础类,您可以随意命名,只要它符合 Dart 类声明格式。
    • MyApp 类继承自 StatelessWidget(一个不需要可变状态的 Widget)。
    • 我们将重写 build 方法并返回 MaterialApp。在 home 属性中,我提供了一个 MyHomePage 对象,它将作为页面显示的主类。
    • Flutter 使用 Material Design,以在跨平台提供相似的外观。
    是的,编辑器会显示错误,因为我们还没有创建 MyHomePage。我们将在下一步创建它。
  4. 右键单击 lib 文件夹,然后悬停在 new item 上,以创建新的 Dart 文件。将其命名为 myhomepage.dart。您只需键入文件名,它会自动添加后缀。
  5. 将以下代码添加到 myhomepage.dart 文件中:
    import 'package:flutter/material.dart';
    
    class MyHomePage extends StatelessWidget{
    
      final String title;
      MyHomePage({this.title}) {
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(title,style: new TextStyle(fontSize: 15.0),),
          ),
        );
      }
    } 
    • 在这里,我们创建了 MyHomePage 类,它继承自 StatelessWidget
    • 创建一个构造函数,并在参数中使用 {this.title},为 final title 变量提供命名参数和值。const final 之间的关键区别在于,const 需要在编译时定义,而 final 变量可以在第一次初始化时定义。
    • 我们需要重写 Widget build(BuildContext context) 方法,并返回一个 Scaffold 对象,其中包含 AppBar 的信息。
    • 在这里,appBar Scaffold 类的属性,需要用 AppBar 对象进行初始化,您可以在其中指定要显示的标题。
  6. 第一次运行,键入 Shift+F10 或按 播放 按钮来运行您的项目。请确保您的模拟器正在运行,以便看到您的应用程序。

    顶部右侧的 Debug 标记表示我们正在 Debug 模式下运行此应用程序。至此,我们完成了任务#1

  7. 现在是任务#2。由于 Flutter 中的一切都是 Widget,我们将创建一个新的类 MySnackBarClass,并将其对象提供给 MyHomePageScaffold 的 body 属性。因此,MyHomePage 的 build 方法将如下所示:
        Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(title,style: new TextStyle(fontSize: 15.0),),
          ) ,
          body: new MySnackBarClass()
        );
      }
    新增部分以粗体标出。
  8. 现在创建 MySnackBarClass 类,并提供以下代码:
    class MySnackBarClass extends StatelessWidget{
      @override
      Widget build(BuildContext context) {
        return new Container(
          child: new Center(
              child: new Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <widget>[
                  new RaisedButton(
                    onPressed: (){
                      final mySnackBar = new SnackBar(
                          content: Text('Hello from SnackBar'), //text to display
                          duration: Duration(seconds: 10),    // Duration to display
                      );
                      Scaffold.of(context).showSnackBar(mySnackBar);
                    },
                    child: new Text("Click Me"),
                    color: Colors.amber,
                  ),
                ],
              )
          ),
        );
      }
    }
    </widget>

    代码解释

    • 在这里,我们返回一个 Container 对象,它将充当放置各种 UI 元素的容器。
    • 我们希望内容居中对齐页面,因此我们使用了 Center Widget,并将其 child 对象设置为 Columns,将其主轴对齐设置为 center
    • 由于我们可以在 Column Widget 中放置多个 Widget,因此它有一个 children 属性而不是 child 属性,它接受 Widget 数组。
    • 在这里,我们提供了 RaisedButton 对象,其颜色为 amber,标签为 Click Me,onPressed 是一个匿名函数,用于显示 SnackBar
    • 我们创建了一个带有文本和可见持续时间的 Snackbar 对象。
    • 最后,我们使用 Scaffold.of() 方法来显示 SnackBar
  9. 使用 Hot reload 来刷新模拟器。如果不起作用,您可以执行 hot restart。

    所以任务#2在这里完成。

  10. 为了添加底部导航栏,我们需要利用 Scaffold 类的 bottomNavigationBar 属性。我们将采用与任务#2相同的方法,创建一个单独的类来处理底部导航栏。更改后,MyHomePage 中 build 方法的代码将如下所示:
       Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(title,style: new TextStyle(fontSize: 15.0),),
          ) ,
          body: new MySnackBarClass(),
          bottomNavigationBar: new MyBottomNavigationBar(),
        );
      }

    在这里,我们将创建 MyBottomNavigationBar 类来为底部栏提供 UI 元素。

  11. 创建 MyBottomNavigationBar 类,以下是代码示例:
    class MyBottomNavigationBar extends StatelessWidget{
      @override
      Widget build(BuildContext context) {
        return new ButtonBar(
          alignment: MainAxisAlignment.center,
          children: <widget>[
            new IconButton(icon:new Icon(Icons.airline_seat_recline_normal), onPressed: (){
              print('hello');
            })
          ],
        );
      }
    }
    这是对以上代码的解释:
    • 我们正在返回一个 ButtonBar 对象,它提供了在其 Widget 树中放置多个 Widget 的能力。
    • ButtonBar 的对齐方式设置为 center,以居中显示内容。
    • 创建一个带有 airline_seat_recline_normal 图标类型的 IconButton
  12. 最后一次 Hot reload 来查看您的更改。

至此,本教程结束,敬请期待更多内容。您也可以在 GitHub 上查看源代码 https://github.com/thatsalok/FlutterExample/tree/master/tutorial1

关注点

请阅读以下文章。它们可能会让你大致了解当前的风向。

  1. Flutter — 你可能喜欢它的 5 个理由
  2. Flutter 的革命性之处
  3. 为什么 Flutter 使用 Dart

Flutter 教程

  1. Flutter 入门:教程 2 – StateFulWidget
  2. Flutter 入门:教程 3 导航

Dart 教程

  1. DART2 Prima Plus - 教程 1
  2. DART2 Prima Plus - 第二课 - LIST

历史

  • 2018 年 7 月 5 日:初版
  • 2018 年 7 月 11 日:更新了其他教程引用。
  • 2018 年 7 月 14 日:更新了其他教程引用,进行了一般性文章修复。
© . All rights reserved.