最近关注的很多公众号都推了关于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插件
打开Android Studio,File>Settings>Plugins 搜索Flutter,点击Serch in respositories,点击install,弹窗是否安装其他插件(Dart),点击Yes。安装完成后重启Android Studio。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.).
安装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的目录。这里注意项目名是不能有大写字母的。尝试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。