整理了一些资料用来分享给小伙伴们。分享内容大概4部分。
-
跨平台方案的简介
-
Flutter 和 Dart 的 简介
-
安装 和 Flutter Demo 简介
-
Stream 介绍
跨平台开发方案
为什么要跨平台开发
因为原生开发有一些优劣:
优点:
1.可获取平台全部开放功能,比如摄像头,蓝牙等;
2.用户访问应用的感受通常是速度快、性能高、体验好;
缺点:
1.为特定平台开发,综合成本高,不同平台维护需要人力成本;
2.动态化能力弱,大多数情况下,新功能更新只能发版;
如果使用跨平台开发就可以避免一些问题,同时往往能节省人力,节省开发时间。
有哪些跨平台开发方案
可归为以下3个阶段
- 1.青铜时代。采用 WebView 容器(广义) + JavaScript Bridge ;
- 2.白银时代。用JavaScript开发,绘制交由 Native 接管(JavaScript VM + Native UI);
- 3.黄金时代。某开发语言 + engine(每个平台单独的绘图引擎)。
第一个阶段,Web与Native分离, 使用 JavaScript Bridge 协议桥接 WebView(具体来说就是在网页加载完成后插入 js 代码,实现网页与原生的通信)。这个阶段的跨平台只是伪命题,实际上就是 WebView。
第二个阶段,使用虚拟机平台将 js 代码转换为原生控件。具体来说一版使用各个开发语言,(RN-javaScript,Weex-Vue)各种语言,打包成 JS 代码,根据提供的(framework,core,Bridge),最终映射成为操作系统原生库展现 app。
第三个阶段,搞一个系统,对接操作系统 sdk 底层。具体来说是一个自绘引擎,使用开发语言(例如 dart)通过自绘引擎(针对不同的操作系统,开发专用的自绘引擎),直接在操作系统绘制图形界面。这样来实现顶层统一,产物不同。因为不使用系统 sdk 提供的组件,所以比较自由,官宣可以做到一个像素点可控。同时因为直接绘制界面,流畅性非常高。
不过也有缺点:涉及到平台层时还是需要原生开发介入实现相应插件。
对比第二和第三方案
虽然这是比较早的时候的对比,但是可以看出,第三方案跟第二方案对比还是很有优势的。
Flutter 和 Dart 方案介绍
进入主题。
Flutter
有多少产品在使用它
alibaba 闲鱼, 百老汇音乐剧, tencent NOW Live直播项目, Abbey Road的Topline(帮助艺术家录制歌曲), JD 金融项目, Google ad 等
在官方宣传网址 itsallwidgets.com 上还有非常多的产品用到了Flutter。
网站上还有很多开源的项目,例如 Sandwhich三明治 。
在 github 上的项目个数大概如下:
preject | 个数 |
---|---|
flutter | 3w |
RN | 10w |
OC | 12w |
swfit | 14w |
iOS | 27w |
android | 85w |
社区如何
这么多开发者使用,也反映了google 老大哥的带动力之大。有非常多的社区,来发展这个比较年轻的语言。
flutter | 社区 | flutter | 社区 | |
---|---|---|---|---|
flutterchina.club | 中文网站 | stackoverflow | Q A | |
GITT ER | github的即时聊天 | Google Groups | Google网上论坛 | |
Medium | 博客平台 | slack | 协作聊天 | |
YouTube | 视频 | Discord | 实时通话软件 |
历史
当前规模的现状,Flutter 用了很长时间吗?
-
Flutter的第一个版本被称为“Sky”,运行在Android操作系统上。它是在2015年Dart开发者峰会上亮相的,其目的是能够以每秒120帧的速度持续渲染。
-
Beta1版本于2018年2月27日在2018 世界移动大会公布。
-
1.0版本于2018年12月5日(北京时间)发布。
-
2019年2月发布1.2版本。目前最新为1.5版本。
Beta1版本是从2018年才开始发展,到现在,基本才只有一个多年头。如果从1.0版开始算起,正式版的话才半年,真的非常年轻。
发展 - Roadmap 2019
在 github 上,flutter 更新频率非常高,最新版已经到1.5+。对于2019年的 flutter 计划,官网上也做出了规划。
-
Fundamentals 基本(bug,性能,测试,api文档)
-
Ease of Adoption (模板,文档,组件)
-
Ecosystem(C/C++,生态插件,通知,数据存储)
-
Support for platforms beyond mobile(键鼠,Web,macOS,Windows)
-
Tooling(开发工具的改进)
-
Change(在2019年删除了对动态更新的支持)
最新的master 分支已经加入了macOS 的代码。
有三个原因使得 flutter 对热更新暂时不准备付出太多的精力:因为系统平台(iOS、Android)对热更新的态度尚且不明确;因为热更新使用下发代码的方式更新,所以不可避免存在安全问题;第三是还没有一个统一平台来做代码下发这件事,如果实现不得不由各个项目开发团队自己搭建。
Dart
Flutter 最终选择了 Dart 作为开发语言,Dart 是什么,为什么选择 Dart 呢?
Dart简介
时间线如下
-
2011年10月 - Google Chrome(V8引擎)
-
2015年被移出 Chrome
-
Sky 诞生,服务器,前端全面发展
-
2018年8月 发布重构版 Dart 2.0
Dart 的历史也是有波折的。Dart 最早在2011年被 Google Chrome(V8引擎)团队创立,使用于 Web 网页,立志要取代 JavaScript 这个繁重的 Web 应用。
然而,2014-2105年,由 NodeJS 开源项目引领,诞生了一系列明星项目如React、React-Native、Vue 等基于 JS 的前端开发框架,当时还流行一句话,“凡是能被JS实现的,最终都要被JS实现”。
于是 Dart 在2015年被移出 Chrome。
同时在2015年Dart开发者峰会上,Sky 诞生,运行在Android操作系统上。其的的是能够以每秒120帧的速度持续渲染。它也是 Flutter 改名之前版本。像 Javascript 一样,Dart在服务端和浏览器前端也在不遗余力的发展:服务端可以编写命令行程序,前端可以编译成Javascript运行在浏览器中。Google的另一个前端大杀器Angular也有对应的Dart版本。在Google的未来操作系统Fuchsia中,Dart被指定为官方的开发语言。这些发生在2015-2017年。
船小好调头,也正是使用者较少,没有历史包袱,Dart的创造者们总结了Dart1.0版本的优缺点,决定打造一个运行更快、更加安全的强类型语言Dart2.0。2018年8月正式发布 Dart 2.0 ,目前稳定版为 2.2(19年02月27发布)。
目前,Dart 在移动端有 Flutter,web 有 Dart for the web,服务端有 Server-side Dart。
Dart 适合移动端吗
目前看比较适合。
- 1) Dart是AOT (Ahead Of Time)编译的,可编译成快速、可预测的本地代码。
- 2) Dart也支持JIT (Just In Time)编译,开发周期快(状态热重载);
- 3) Dart可以更轻松地创建以60fps运行的流畅动画和转场。它的启动速度也快得多。
- 4) Dart使Flutter不需要单独的声明式布局语言,如JSX或XML。
- 5) 开发人员发现Dart特别容易学习,因为它具有静态和动态语言用户都熟悉的特性。
Dart 支持两种编译模式,AOT 和 JIT。开发环境使用 JIT,借助虚拟机,随时修改代码,随时看到效果,可以实现亚秒级的热重载。发布环境使用 AOT,打包出经过各种编译优化的包,不论是在安装包安装速度,和包内程序运行速度都要很多优势。
Dart 最初就被设计目标就是持续渲染,不卡顿。所以有很多设计上的优势保证fps。
- 1) AOT 编译就像原生代码的 AOT 编译,与“JavaScript桥梁”方案相比,天然少了桥的过程。
- 2) Dart 在 抢占式调度、时间分片和共享资源 方面权衡诸多条件,选用最适合界面特点的方案:单线程,程显式让出(使用 async/await、Future 和 Stream)CPU。
- 3) 访问共享资源(内存)的情况下,在很多语言中都需要使用锁。但在回收可用内存时, 锁会阻止整个应用程序运行。Dart使用先进的 分代垃圾回收和对象分配方案,该方案对于分配许多短暂的对象(对于Flutter这样的反应式用户界面来说非常完美,Flutter为每帧重建不可变视图树)都特别快速。
Dart的另一个好处是热重载,Flutter不需要从程序中拆分出额外的模板或布局语言,如JSX或XML,也不需要单独的可视布局工具。借助热重载,可视化编辑就不需要了。体验下来,开发中,从页面开始创建,到添加资源,请求,封装模型,修改 UI,添加事件,页面最终完成,你都不需要重新编译,一切都是所写即可见。
安装 和 Flutter Demo 简介
这里就不多讲了,参考之前的博客。
安装 和 Demo
Flutter 《一》 安装和配置,QA 介绍了安装问题;一些官方的 QA。
Flutter 《二》项目 Demo 运行,Dart 语言简单学习 几个简单的 Demo。速学 Dart 语法。
Wdiget 和 布局
Flutter 《三》常用组件 & Week Video 一切皆是 Widget,Widget 认识和学习。
布局方面跟之前用到的 Texture 盒式布局异曲同工,所以没有单独写博客。其实上手还是比较简单的,有兴趣参考Texture(ASDK)的理解和使用,理论还是相通的。
数据转 model
dart提供的库 dart-convert 可以实现将 json 转换为对象。样例的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class User {
int id;
String name;
String avatar;
User({
this.id,
this.name,
this.avatar,
});
factory User.fromJson(Map<String, dynamic> json) => new User(
id: json["id"] == null ? null : json["id"],
name: json["name"] == null ? null : json["name"],
avatar: json["avatar"] == null ? null : json["avatar"],
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
"name": name == null ? null : name,
"avatar": avatar == null ? null : avatar,
};
}
同样有很多方案提供实时转换,但是我还是用了应用来转换。 macOS 有一款应用 Paste JSON as Code • quicktype.app 可以轻松转换json 到各个常用语言的模型。
调试
在 VS Code,使用 DevTools 可以 方便的调试页面。
DevTools提供的功能:widget 树,debug paint,slow animation;timeline,memory,logging,Debugger 等。还可控制程序热重载喝热重新运行。
Stream
顾名思义,Stream 就是流的意思,表示发出的一系列的异步数据。可以简单地认为 Stream 是一个异步数据源。它是 Dart 中处理异步事件流的统一 API。
使用数据流可以更好管理项目代码,设计项目模式,节约设备资源(避免持有大文件)等。
Dart 中,集合(Iterable或Collection)表示一系列的对象。而 Stream (也就是“流”)也表示一系列的对象,但区别在于 Stream 是异步的事件流。比如文件、套接字这种 IO 数据的非阻塞输入流(input data),或者用户界面上用户触发的动作(UI事件)。
集合可以理解为“拉”模式,比如你有一个 List ,你可以主动地通过迭代获得其中的每个元素,想要就能拿出来。而 Stream 可以理解为“推”模式,这些异步产生的事件或数据会推送给你(并不是你想要就能立刻拿到)。这种模式下,你要做的是用一个 listener (即callback)做好数据接收的准备,数据可用时就通知你。
Future
第一个概念叫 Future。 Future 表示稍后获得的一个数据,所有异步的操作的返回值都用 Future 来表示。但是 Future 只能表示一次异步获得的数据。 而 Stream 表示多次异步获得的数据。
1
2
Future<T>
Stream<T>
获得 Stream
数据流的发出点
将集合(Iterable)包装为 Stream Stream 有3个工厂构造函数:fromFuture、fromIterable 和 periodic,分别可以通过一个 Future、Iterable或定时触发动作作为 Stream 的事件源构造 Stream。
使用 Stream 读文件 读文件的方式有多种,其中一种是使用 Stream 获得文件内容。
下边示例一个集合转换为 steam 并进行后续操作的例子。
1
2
3
//获得 Stream
var data = [1, 2, 3, 4];
var stream = new Stream.fromIterable(data);
订阅 Stream
数据流的接受点
1
2
//订阅
stream.listen((e) => print(e));
订阅和高级订阅(onData、onError和onDone)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//订阅 Stream
stream.listen((e) => print(e), onDone: () => print('Done'));
//1 2 3 4 Done
//订阅管理 StreamSubscription
var sub = stream.listen(null);
sub.onData((e) {
if (e > 2)
sub.cancel();
else
print(e);
});
sub.onDone(() => print('done'));
//1 2
区别在于高级订阅返回一个 StreamSubscription 的对象,这个对象有 onData,onDone,onError 方法。
单订阅模式 和 多订阅模式
1
2
3
4
5
6
//多订阅(broadcast)
var bs = stream.asBroadcastStream();
assert(bs.isBroadcast == true);
bs.first.then(print);
bs.last.then(print);
//1 4
上边的 stream 只支持 一个数据流接受,接受完毕就监听不到数据流了。 可以使用 asBroadcastStream()方法返回一个同样类型(T)的 stream,这样就可以多次订阅了。
Stream 的集合特性
Stream 和一般的集合类似,都是一组数据,只不过一个是异步推送,一个是同步拉取。所以他们都很多共同的方法。
除了既有方法,如果需要自定制,Stream 还提供一些数据转换协议。继承 StreamEventTransformer 并且实现必有方法即可使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//常见集合方法
//stream.first.then(print);
//stream.firstWhere((e) => e > 3, orElse: () => 0).then(print);
//...
//last, length, isEmpty, any, every, contains, elementAt, where, skip, take,
//map, reduce, expand, toList, toSet
//StreamTransformer
class MyTransformer extends StreamEventTransformer {
...
}
最后
这篇文章先到这里了。整理分享还是要注意些问题:既要广泛了解,让大家有个认识;又不能太过深入,否则大家不能理解,时间也不允许。不像编程,只要解决问题就好了。
还有下一篇,包含 state 更新方案,原生项目和 Flutter 项目互调等精彩内容,不容错过。
参考
Flutter之StatelessWidget StatefulWidget和Element关系浅析
谷歌推出简化APP开发:Google Flutter的功能和优势
编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言的区别