前言:在2017年谷歌开发者大会上, Google展示了最新的开发者产品和平台,其中flutter和Material Design(纸墨设计)也被提及了。关于flutter新技术,笔者第一次接触,看了官网的一些基础部分和一些博客,特此在这做记录,有些引用到别人的地方会提供相关的链接,如果你也是做移动开发的,欢迎一起关注flutter,一起学习!
一、Flutter简介和未来前景
Flutter是Google使用Dart语言开发的移动应用开发框架,使用一套Dart代码就能构建高性能的iOS和Android应用程序(即App),并且在排版、图标、滚动、点击等方面实现零差异。
Flutter简介:
-
跨平台应用开发框架
想象一下,一套代码可以同时跑安卓和苹果手机,而且性能跟原生一样,节省人力,提高开发效率,这一大亮点就足够吸引你去study。虽然reactnative(简称RN)也可以达到跨平台的目标,但是两者还是有所区别。后面会对Flutter和RN做一个对比。 -
简单高效的Dart
Dart语言是一种面向对象编程语言,跟其他面向对象编程语言差别不大,所以有java基础的入门没什么难度。谷歌选择Dart主要原因是:Flutter需要不断快速地创建和销毁短生命周期对象,Dart的垃圾回收机制非常适合用于完成这项任务。
在Flutter里,界面布局直接通过Dart编码来定义,不需要使用XML或模板语言。 -
Flutter框架内置了一组丰富的设计控件
一切皆控件,控件是每个Flutter应用程序的基本构建块,与分离视图、控制器、布局和其他属性的框架不同,Flutter具有一致的统一对象模型:控件。一个控件可以定义:结构元素(比如按钮或菜单)、风格元素(比如字体或颜色方案)、布局方面(比如填充)、一些业务逻辑等。 -
Flutter提供了热加载功能(Hot Reload)。
-
支持Windows,Mac和Linux
-
分层结构
image.png
Material层:根据Material Design设计规范开发的 Widget 库。这里的代码都位于 lib/src/material 目录下,里面包含了几乎所有 纸墨设计 规范里面定义的控件。比如 FloatingActionButton、BottomSheet 等。Material 层 是使用了 Widget 层的控件来构建的 。
Widget层:定义了Flutter 框架的基础 UI 控件,比如 Text、Padding、ListView 、ImageView 以及事件处理等。Widget 层依赖下面的Rendering 层来构建的。
Rendering层:绘制View视图。
Engine层:Flutter能够在iOS和Android上运行起来,依靠的是一个叫Flutter Engine的虚拟机,Flutter Engine是Flutter应用程序的运行环境,开发人员可以通过Flutter框架和API在内部进行交互。
Read More:https://blog.csdn.net/zhoumushui/article/details/79548075
Flutter未来前景:
对于flutter的未来前景,有些人看好,有些人不怎么看好,从我个人的角度看,一个新技术的诞生必定有它存在的原因和价值,毕竟,谷歌会耗费精力去开发flutter,未来它也许会颠覆移动开发,即使目前而言,移动开发已趋向于饱和。
我比较看好flutter,因为它不仅仅是跨平台的开发框架,其响应式编程的思想也是一大亮点。以往的app开发方式显然存在某些弊端,才会出现新的技术框架来高效开发更优秀的应用程序。有些开发者接触flutter后,感觉其在性能方面更适合用于开发游戏,因为它帮你省掉了很多繁琐的工作。
当然,flutter还很年轻,仍然在技术验证和研发阶段,目前没办法做到面面俱到。
相关链接参考:
- https://blog.csdn.net/johnWcheung/article/details/78984232
- http://www.infoq.com/cn/news/2017/11/Why-native-app-developer-Flutter
二、Flutter和ReactNative的比较
flutter在不久的将来应该会火,目前已经成为reactnative的竞争对手,下面对比一下flutter和reactnative这两者的优势和缺点。
- react native的优势
(1)比原生开发更为灵活和高效,对比h5的体验更好,性能方面接近原生。
(2)可以远程调试代码,热加载
(3)轻松实现热更新,可以在线更新代码
(4)跨平台,实现一套代码跑安卓和ios移动设备
(5)React Native实现不了的,可以通过原生来实现,可以互补 - react native的缺点
(1)即使是跨平台,但是不同平台的Api特性与显示不一定一致,有些组件的显示效果也是有平台方面的差异。
(2)调试必须依赖于网络,如果没有网络是无法load js的代码。
(3)增大了app的体积,reactnative集成了不少的插件和库,所以即使不怎么写代码,app也有十M左右
(4)Android上的兼容性问题
上面已经提及了flutter的一些情况,现在从下面几个方面对比这两者:
- 性能和体验
RN能达到60fps,而flutter实现120fps的渲染性能,所以流畅性,Flutter比RN好很多。
和React Native一样,Flutter也提供响应式的视图,Flutter采用不同的方法避免由JavaScript桥接器引起的性能问题,即用名为Dart的程序语言来编译。Dart是用预编译的方式编译多个平台的原生代码,这允许Flutter直接与平台通信,而不需要通过执行上下文切换的JavaScript桥接器。编译为原生代码也可以加快应用程序的启动时间。
Read More:https://blog.csdn.net/zhoumushui/article/details/79548075
- 开发语言
RN使用JavaScript,js是用于Web开发的脚本语言,通过js调用原生的UI组件必须经过一层桥接器。
flutter使用dart语言开发,dart是一门面向对象编程语言,可以用于原生开发。
这里不比较两门语言的优缺点,因为各取所需,适合才是最重要的。 - 热加载
RN和Flutter都能实现热加载,区别在于,如果使用真机调试的话,RN可以远程热加载,不依赖于数据线;Flutter要通过数据线连接上设备。 - 维护成本
原生开发的维护成本一直居高不下,所以才有这些跨平台框架的产生。
RN开发效率高,维护成本相比于原生也降低了不少,而且懂web开发的人都可以很快入门RN开发。目前国内使用RN的人数很多。
而对于flutter,必须要有一个学会Dart语言的开发者才可以去维护它,目前flutter的活跃量相比RN就少好多。
三、Dart语言(https://www.dartlang.org/samples)
(1)每个app都有一个main()函数
image.png image.png(2)声明一个变量
在Dart代码的类型安全中,大多数变量不需要明确类型,因为有类型推断。
image.png
默认值:未初始化变量的初始值为null。即使具有数字类型的变量初始值也是空的,因为数字类型的变量也是对象。
image.png
在生产模式中,assert()调用被忽略。在“检查”模式下,除非条件为真,否则断言(条件)将引发异常。有关详细信息,请参阅断言部分https://www.dartlang.org/guides/language/language-tour#assert。
如果您不想更改变量,请使用final或const,而不是var,或者在类型之外使用。final变量只能设置一次;const变量是编译时常量。
关于Dart语言的const和final的区别可以参考http://han.guokai.blog.163.com/blog/static/136718271201321911119331/
关于Dart变量的使用可以看官网
https://www.dartlang.org/guides/language/language-tour#variables
JavaScript中为false的几种情况
false,null,undefined,“”,0,NaN
而Dart Code有所不同
image.png
(3)关键字
image.png1 Words with the superscript 1 are built-in identifiers. Avoid using built-in identifiers as identifiers. A compile-time error happens if you try to use a built-in identifier for a class or type name.
(ex:上标1的单词是内置标识符。避免使用内置标识符作为标识符。如果您试图为类或类型名使用内置标识符,则会出现编译时错误)
2 Words with the superscript 2 are newer, limited reserved words related to asynchrony support added after Dart’s 1.0 release. You can’t use async
, await
, or yield
as an identifier in any function body marked with async
, async*
, or sync*
. For more information, see Asynchrony support.
(ex:上标2的单词是较新的,有限的保留词,与在1版本发布后添加的异步支持相关。在任何标记为 async
, async*
, or sync*
的函数体中,您都不能使用async,await,或yield作为标识符。有关更多信息,请参见 Asynchrony support)
(4)类class
四、Flutter开发环境搭建(windows系统)
由于本人使用的是windows系统,下面介绍windows搭建flutter开发环境,如果你是mac,可以参考https://www.jianshu.com/p/a1344cfea21d
- 下载flutter SDK
git clone https://github.com/flutter/flutter.git
(注意要先安装git,如果未装的请自行百度安装教程)
- 如果你没有翻墙,这里需要配置一下镜像服务器,要不然后面flutter doctor会一直失败
在高级系统设置——环境变量加多两个环境变量:
PUB_HOSTED_URL https://pub.flutter-io.cn
FLUTTER_STORAGE_BASE_URL https://storage.flutter-io.cn
- 在系统配置flutter的命令使其能全局使用,同样打开高级系统设置——环境变量,在Path变量中添加flutter的路径
-
打开cmd窗口,输入
flutter doctor
这样它就会自动下载一些依赖库和基础控件
image.png
下载完成后:
image.png -
VSCode配置【https://code.visualstudio.com/docs/?dv=win】
(这里也可以使用android studio3.0【http://rj.baidu.com/soft/detail/27390.html?ald】或者IntelliJ IDEA Community【https://www.jetbrains.com/idea/download/#section=windows】)
输入flutter,New Project创建一个项目或者打开命令提示符,进入想新建flutter项目的文件夹下,输入:
flutter create myDemoFlutter
相关网址推荐:
- https://www.jianshu.com/p/7cbf82b4854e
- https://blog.csdn.net/hekaiyou/article/details/52874796?locationNum=4&fps=1
五、Flutter开发一个demo App
-
按照以上教程运行一个helloworld的项目,代码和目录结构如下图所示:
image.png
用数据线连接上你的安卓设备,按F5即可运行app到手机上,运行效果如下图所示:
image.png
- 热加载功能
只要你在代码中修改了相应的布局,当你ctrl+s保存代码后,它会自动将修改的样式运行到手机app上,开发相当方便。 -
接下来开始撸代码,写一写简单的界面
(1)首先看下图的代码,main函数采用了所谓的箭头函数写法,MyApp是继承至一个StatelessWidget类,然后重写一个build()方法,返回一个MaterialApp(即widget控件)。
image.png
官方解析:
-
本示例创建了一个 Material app 。 Material 设计语言是一套移动设备和网页上的视觉设计标准。Flutter 提供了一套丰富的 Material Widgets 。
-
该 app 继承了使它本身成为一个 widget 的 StatelessWidget 类。在 Flutter 中,大多数时候一切都可以看作 widget , 包括 alignment,padding 和 layout 。
-
Material 库中的 Scaffold widget 提供了默认的应用栏 (app bar),标题和构成主页面 widget 树结构的 body 属性。 widget 的子树可以非常复杂。
-
widget 的主要工作是提供一个
build()
方法,描述如何根据其他更低层级的 widget,来对这个 widget 进行展示。 -
本示例的 widget 树由包含了 Text child widget 的 Center widget 组成。Center widget 可将它的所有子树对齐到屏幕中心。
(2)下面根据官网写一个简单的例子,代码如下:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Startup Name Generator',
theme: new ThemeData(
primaryColor: Colors.blue
), //改变主题样式
home: new RandomWords(), //定义子组件为有状态控件RandomWords的实例
);
}
}
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
//定义状态类RandomWordsState
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[]; //用于保存随机字符串词组
final TextStyle _biggerFont = new TextStyle(fontSize: 18.0);//字符串的样式
final _saved = new Set<WordPair>(); //保存选中的值
void _pushSaved(){
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context){
final titles=_saved.map((pair){
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
);
});
final divided=ListTile.divideTiles(
context: context,
tiles: titles
).toList();
return new Scaffold(
appBar: new AppBar(
title: new Text('Saved Word'),
),
body: new ListView(
children:divided,
),
);
},
)
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('ListView'),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.list),onPressed: _pushSaved),
],
),
body: _buildSuggestions(),
);
}
Widget _buildSuggestions() {
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
//通过ListView自带的函数itemBuilder,向ListView中塞入行,变量 i 是从0开始计数的行号
//此函数会自动循环并计数
itemBuilder: (context, i) {
if (i.isOdd) return new Divider(); ////奇数行塞入分割线对象
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
},
);
}
Widget _buildRow(WordPair pair) {
final hasSaved = _saved.contains(pair);
//ListTile和Text都是material.dart中的基础控件
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: new Icon(
hasSaved ? Icons.favorite : Icons.favorite_border,
color: hasSaved ? Colors.red : null,
),
onTap: () {
setState(() {
if (hasSaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
}
效果图如下:
image.png
相关链接:
- https://segmentfault.com/a/1190000013672695
- https://www.oschina.net/translate/5-reasons-why-you-may-love-flutter
六、调试和性能监测
官网关于debug app的链接可以查看https://flutter.io/debugging/。
Flutter Widget Inspector是用于可视化和探索Flutter Widget树的强大工具,官网对于该工具的说明可以查看此链接
http://doc.flutter-dev.cn/inspector/。
需要说明一点的是只有Android Studio和IntelliJ IDEA两个工具适用,VSCode没有这个功能。
下面以AS3.0开发工具说明一下该功能:
-
首先要在AS下载相应的插件,比如Dart和Flutter。
点击FIle-Settings打开Plugins,搜索dart和flutter,安装好相应的插件
image.png
这里安装这两个插件好像要翻墙,所以要科学上网,如果你不能翻墙,可以跟我要Dart和Flutter插件库,通过本地来安装。
-
安装好之后重启android studio,新建一个FLutter Project,然后运行App
image.png -
最后打开Flutter Inspector可以查看Widget和Render Tree
image.png
点击Toggle Select Widget Mode,再点击app上的每个布局控件,可以查看相应的属性和值。
-
打开Android Profiler可以查看CPU和MEMORY的一些使用情况
image.png
通过AndroidStudio来开发和调试也是相当方便的,只是对于电脑的性能要求有点高,VScode编辑和开发比较轻便,但是调试方面没有AS好。
网友评论