初识Flutter

最近关注的很多公众号都推了关于Flutter的文章,还有就是Airbnb放弃React Native的新闻。Google昨天发布了Flutter的第一个预览版本,虽然使用的是完全不会的Dart,但是还是想着来试试。

下面是公众号文章对Flutter的描述:

Flutter 是由 Google 的工程师团队打造的一款移动 UI 框架,它使用的是 Google 自己开发的网络编程语言——Dart 语言,因此,开发者只要使用过 Java 或 JavaScript 之类的语言,那么 Flutter 也极易上手。

Flutter 旨在帮助开发者创建拥有美观 UI 界面、高性能、高稳定、高帧率、低延迟的跨平台(Android 和 iOS)移动应用。Flutter 的界面设计与 Web 应用类似,所以开发者很容易在 Flutter 上找到类似 HTML/CSS 编码的感觉。

和 React Native 相比,虽然使用的语言不同,但 Flutter 也提供响应式的视图。此外,Flutter 开发出来的应用在不同的平台用起来跟原生应用具有一样的体验。例如,返回图标 Android 和 iOS 是不一样的;滚动内容滚动到底的反馈也是不一样的。

搭建环境的过程主要参考:Flutter文档

安装Flutter和Dart插件

The Flutter plugin powers Flutter developer workflows (running, debugging, hot reload, etc.).
The Dart plugin offers code analysis (code validation as you type, code completions, etc.).

打开Android Studio,File>Settings>Plugins 搜索Flutter,点击Serch in respositories,点击install,弹窗是否安装其他插件(Dart),点击Yes。安装完成后重启Android Studio。

安装Flutter SDK

参考:文档

直接在Android Studio install SDK会因为某些原因非常慢,所以看这篇文章,可以镜像下载SDK。下载完成后解压。

配置Path路径,新添加一个flutter的bin目录路径。

双击flutter解压后文件目录下的flutter_console.bat,输入flutter doctor检查环境的问题并且会提示修改的命令。

按照提示一步一步执行命令解决就可以了。
比如说我的提示,需要同意Android licenses,还需要在Idea中配置Flutter插件。

解决完后再flutter doctor检查一遍看看。

新建Flutter项目

File>New>New Flutter Project,选择Flutter Application,点击Next。

选择之前安装的Flutter SDK的目录。这里注意项目名是不能有大写字母的。

这里可以选择添加kotlin和iOS的支持。

新建完项目之后就是这个样子。

点运行看一下效果,第一次有点慢。

尝试Hot Reload

Flutter提供了快速开发,具有热重加载d的功能,能够在不重启或丢失应用程序状态的情况下重新加载运行中的应用程序的代码。只需对源代码进行更改,点击黄色闪电的按钮就可以看到更新之后的样子了。

简单的分析main.dart

1 main()

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

这是Dart中单行函数的简写方式。

2 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 Demo Home Page'),
    );
  }
}

它的实例在main()中传递给runApp()。可以从注释中看出来这个MyApp是应用的根widget,MyApp继承了StatelessWidget这将会使应用本身也成为一个widget。

widget提供一个build()方法来描述如何根据其他较低级别的widgets来显示自己,比如这里重写的build()返回了一个MateriaApp对象,传入了三个参数进构造器,MatrialApp也是一个widget,代表使用Material Design风格的应用,提供了一些属性,比如这里用到的title、theme、home都是它的属性,其他具体看这里

  • title:定义任务管理窗口界面所看到应用名字的。
  • theme:定义应用所使用的主题颜色,定义了 primaryColor、accentColor、hintColor 等颜色值。也可以通过这个来指定一个 ThemeData 定义应用中每个控件的颜色。
  • home:这个是一个 Widget 对象,用来定义当前应用打开的时候,所显示的界面。

在这个例子中,theme使用的就是一个ThemeData,其中指定了一个参数primarySwatch为蓝色。home使用的是一个自定义的class MyHomePage,传入了一个title值。

3 MyHomePage

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

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

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

不同于上面的MyApp,MyHomePage是继承了StatefulWidget,注释也有解释这一点,stateful意思就是它有一个包含影响它界面表现的状态对象,这里的状态对象就是_MyHomePageState,它定义在下面。

这个MyHomePage其实是状态的配置类,它包含由父widget提供的值(比如这里的title),我猜第一行应该就是MyHomePage的构造器吧。

statless和stateful
  • Stateless widgets 是不可变的,这意味着它们的属性不能改变——所有的值都是 final。
  • Stateful widgets 持有的状态可能在 widget 生命周期中发生变化,实现一个 stateful widget 至少需要两个类:
    • 一个 StatefulWidget 类;
    • 一个 State 类
  • StatefulWidget 类本身是不变的。

最后它重写了createState(),添加了状态对象_MyHomePageState。

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

这个状态类是最复杂的一个了。_MyHomePageState extends State<MyHomePage>表示_MyHomePageState是专门用于MyHomePage的State泛型类。

定义了一个_counter变量,定义了一个方法_incrementCounter(),它调用了setState(),这个调用就是去通知有状态改变了,应该去重新调用下面的build()去反映更新后的值。如果知识单纯的改变_counter的值,而不去调用setState(),那么build()就不会调用,界面不会更新。

_MyHomePageState重写的build()中返回了Scaffold。

Scaffold是Material library中提供的一个widget,它提供了默认的导航栏、标题和包含主屏幕widget树的body属性。widget树可以很复杂。

appBar: new AppBar(
  title: new Text(widget.title),
),

这里的widget.title其实就是MyHomePage的title,为标题栏设置了一个Text,值就是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,
      ),
    ],
  ),
),

body部分是一个Center,这是一个布局控件,它只有一个子布局,并且位于它的中间。Center的child是一个Column,mainAxisAlignment指定布局位于中间,下面children属性有两个Text,第一个是一个字符串,第二个指定的是_counter的值,还指定了样式。

floatingActionButton: new FloatingActionButton(
  onPressed: _incrementCounter,
  tooltip: 'Increment',
  child: new Icon(Icons.add),
), 

这一段能猜到是类似Android的浮动按钮,onPressed熟悉指定了点击事件调用的方法,tooltip是长按按钮上方出现的提示语,child指定了一个子控件,是一个带加号的图标。

整个main.dart就是这个样子了,发现在res目录中并没有像Android开发一样的layout文件夹,重点内容都在main.dart中了。

拓展

虽然大部分文档都没有中文的,但是还是有中国社区的,里面有一个小例子,先mark下来。编写你的第一个Flutter App

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

推荐阅读更多精彩内容