Flutter 初见
本文概述:
- 文章以跨平台开发为背景,探讨了跨平台开发技术的发展历史,以及Flutter 的优势。
- 思维导图:
学习跨平台技术的必要性
- 传统移动端原生开发弊端:
- 传统的原生开发需要维护Android 、IOS 两个平台;
- 使用Flutter 进行移动端开发的优点:
- Flutter 为跨平台的UI 框架,
- 真正做到一套代码多端使用,增加代码复用,易维护;
- 在于求职中,若具备跨平台开发能力,将具备更强的市场竞争力;
跨平台开发发展历史:
第一阶段:纯原生开发
- 开发成本大:需要维护Android 与 IOS 两套代码;
- 动态化需求:需求发生变化时,纯原生应用大多需要通过版本升级来更新内容。
- 缺少热更新
- 原生开发不可替代的优势:性能优势
- 混合开发出现的原因:
- 当硬件设备性能提升,反哺开发模式,即,可牺牲一部分性能使用混合开发,以减少开发成本。
第二阶段:基于WebView 的 PhoneGap & Cordova(H5 )
- 出现时机:
- 在20008 年提出
PhoneGap
,其采用HTML + CSS + JavaScript
,依托于Android 内置WebView
实现混合开发,宣称接近原生性能。后衍生出Cordova
,这个是从PhoneGap
中抽离出的核心代码,因为收购原因,所以改了名字,其实还是一套代码;
- 在20008 年提出
- 技术现状:
- 除了简单页面外,在考虑性能时,基本不会采用此种跨平台手段。
- 底层机制:
- 在Android 中使用
WebView
加载HTML
,HTML
传给JS
一个JavaInterface
,Js
通过传入的JavaInterface
进而调用到Android 上的代码。 - 图示:
- 在Android 中使用
- 核心代码:HTML 要与原生进行交互
- Java 代码:使用
WebView
加载HTML
,HTML
传给JS
一个JavaInterface
webview.addJavaInterface(new AndroidPlatform(this),"android");
- Js 代码:
Js
通过传入的JavaInterface
进而调用到Android 上的代码。
<button type= "button" onclick = "android".toast('在JS 中,通过传入的JavaInterface 调用Android 平台的代码(toast)')> 按钮 </button>
- AndroidPlatform.class
public class AndroidPlatform{ private Context mContext; public AndroidPlatform(Context context){ //构造 mContext = context.getApplicationContext(); } @JavascriptInterface public void toast(String msg){ Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show(); } }
- Java 代码:使用
- 技术优点:
- 结构较为清晰,写起来比较简单
- 存在的问题:
- 兼容性太差:因为手机厂商的不同,所以细节上的实现也不同
- 渲染性能太差:加载
HTML
非常缓慢- 并且
HTML
中可能充斥过多JS
代码,而JS
可是解释型语言,其执行效率太差了。 - 补充:Java 不是编译型也不是解释型
- Java 先编译成
xxx.class
文件,再交由虚拟机解释执行;但存在JIT
,且Java9 引入了AOT
- Java 先编译成
- 并且
- 内存泄漏:
WebView 的一大弊端
- 常规手段:将
WebView
放入子进程,用完就杀掉 - 底层机制:在使用
WebView
过程中消耗的内存,Android 不能在不需要的时候将其及时回收,因此导致内存越用越少
- 常规手段:将
- 发展历史:渲染效率
- 思路:使用
WebView
渲染效率太差,那么,如果可以将渲染操作交给原生平台,这就非常好了。 - 结果:Facebook 在2015 年提出
RN(React Navtie)
- 思路:使用
第三阶段:RN 的出现:2015 年 — 2018 年
- 出现时机:
- 2015 年4 月Facebook 开源了JS 框架React 在移动端的衍生物React Native。
- 技术现状:
- RN 学习成本高,且性能仍然存在瓶颈(JS 通过桥与原生进行渲染);
- 2017 年百度全面放弃RN 。
- Facebook + BSD + Patents 许可协议引起的全球风暴,导致BAT 弃用;
- 因为用了RN 后,自己搞出的专利都要免费(其实不是这个问题,实际上是公司之间的纠纷)
- 底层实现机制:渲染交由原生平台,但
Bridge
成本过高- 图示:
- 代码执行逻辑:程序员写好
Js
代码后,通过Bridge
与具体平台交互。平台读取Js
配置后,执行操作(new Button 等),注意,此时使用的是原生代码进行渲染
- 与原生开发相较:更新UI 时
- 原生开发中的
XML
是静态的:在更新UI 时,我们仅需操作的是原生Java
代码 - RN 开发中:所有代码都是使用
Js
,那么在更新UI 时,仍需原生平台通过Bridge
读取Js
代码后,才能更新UI ,相较于原生开发,RN 开发每次操作都需要多走一个Bridge
,那么,Bridge
成本太高。
- 原生开发中的
- 演变历史:
- 思路:如果说,出现一款框架能将我们写好的代码,直接编译成各平台原生开发编译后的结果(机器码),就好了。
- 结果:根据此愿景,衍生出Flutter;
第四阶段:Flutter 的出现:2018 — 至今
- 出现时机:
- Flutter Beta1 于2018 年开发者大会出现于大众视野,甚至还没有发布正式版本时,国内头部互联网已开始联手推广。依托于Google,宣称对标原生性能,具备更加规范的开发模式;
- 技术现状:
- 由咸鱼团队率先引入,并在大厂逐步站稳脚跟。
- 图示:
- 底层实现机制:使用Dart 语言,配合Dart 虚拟机,Flutter 将代码编译后,直接就称为了对应平台的机器码;
- 节省掉了
Bridge
:Flutter 根据不同的平台,编译成对应平台的机器码。- 编译型语言,性能最好,但是没办法跨平台;
- 补充:
- Java 可以跨平台,但是JVM 不能跨平台
- NDK 就不是跨平台,平台是指具体的操作系统;
- DVM 是什么:Dart 语言的虚拟机,就是一个虚拟环境。
- 节省掉了
Flutter 基本介绍:
概述
- Google 跨平台移动UI 框架,可以兼容现有代码,且完全免费开源。
- 使用DVM(dart 虚拟机) 避免了
Bridge
的交互,Flutter 代码在编译后可在移动端平台直接运行 - 补充:Fuchsia 系统
- 在2019 年华为在测试这个系统,这是Google 开发的第三个系统(Google Chrome、Android、fuchsia)
整体架构:
- 示意图:
- FrameWork层:为业务代码提供API
- 提供各种基础组件库,包括各种Widget、动画等
- Engine 层:
- 由C++ 编写,下载的Flutter 时候需要区别不同的操作系统,因为C++ 是不能跨平台的
- Skia:是Android 中绘图的底层,
native
的JNI
代码就是用这个的,Chrome 浏览器中也是这个 - 虚拟机就在这Engine 层
Flutter 发展历史
- 发展历史:
- 补充:
Dart 语言的发展历史
- 因为Google 内部对
JS
的不满,其开发出Dart
语言,并在Chrome 浏览器中内置了Dart 虚拟机
,为Dart 语言
提供了执行环境。由于Chrome 浏览器影响巨大,Dart 语言
也在前端开发中占据一席之地。 Node.js
出现又让Js
焕发第二春,其充斥前端、后端、移动端。甚至出现能被Js 实现的,终究会被Js 实现
等。Dart 语言
也逐渐淡出大众视野,甚至Dart 虚拟机也被从Chrome 中移除了。
- 因为Google 内部对
Flutter 特点:
- 快速开发:热重载
- 是什么:亚秒级修改,跟之前的
instant run
类似- 但AS 提供的
instant run
在修改UI 后,不用重新安装,即可查询到其安装在手机上后的真实效果; - 但是这个有点坑,基本上不用这个
- 但AS 提供的
- 有什么用:节省
反复安装、运行以测试
的时间- 修改UI 后,CTRL + S 就可以看到更新后的UI,不用重新安装、运行。
- 但,这个是有一定弊病的,实质上只重载了特定区域的代码。
- 热重载的底层原理:
- 当我们对项目,修改一部分代码后。Flutter,将我们修改的地方,搞成一个配置文件,交给DVM ;
- 其底层使用的WebSocket ,在PC 端启动一个服务,手机端也连接这个服务,这样就实现全双工通信。
- 是什么:亚秒级修改,跟之前的
- 富有表现力和灵活的UI
- UI 设计师一般都是按照IOS 设计的,但是Android 中往往没有,这个时候需要我们自定义UI ;
- Flutter 内置了许多
widget 组件
,其统一了App 的风格;
- 本地性能:Flutter 宣称其媲美原生性能
- 只是较为趋近而已,Flutter 还是多了一层Engine 层;但是还是算是目前性能最好的了
Flutter 开发与原生开发的对比:
- 从任玉刚大佬的博客可以看出如下几点
- 安装包体积:相同功能
- 原生APK 需要1.3MB
- Flutter APK 需要7.5MB
- 运行性能对比:相同功能
- CPU 资源占用:
- 原生开发CPU 占用率在26.8%,且占用率曲线平稳
- Flutter CPU 占用率在35.5%,且占用率曲线陡峭
- 内存占用:两者类似
- 但Flutter 略高于原生开发
- CPU 资源占用:
- 安装包体积:相同功能
怎么判断一个App 是否是Flutter 开发的?
- 以腾讯 Now 直播为例;
- 将其解压后在lib 目录下,查看发现有libflutter.so 那么就是了;
-
- Flutter 架构中的
Engine 层
就在这个文件
- Flutter 架构中的
- lib 目录中的
.so 文件
是由C/C++ 编译而成的,就是由NDK
开发而成的,其作用可以简单看做Java 类库
Dart 语言基本介绍
地位:
- Google 亲儿子,Flutter 官方指定语言
支持混合编译:JIT & AOT
- 基于
JIT
的快速开发周期- Flutter 在开发阶段采用
JIT
模式,避免每次改动都要进行编译,极大节省开发时间 - 补充:什么是
JIT (just in time)
- 在
Java
在解释执行时,将热点代码段使用JIT
编译成本地代码(机器码);- 在程序执行期间,实时将代码编译成机器码
- Flutter 在
DeBug
模式下,使用JIT
,及时处理热点代码,直接将这段代码部署在终端设备上,避免重复编译 JIT
的缺点:其需要在执行后,挑选出热点代码,编译成机器码,导致Flutter 在DeBug 模式
下的效率不如Release 模式 (使用的是AOT)
- 在
- Flutter 在开发阶段采用
- 基于
AOT
的发布包- Flutter 在发布时,可以通过
AOT
生成高效的ARM
代码以保证应用性能; - Flutter 在
Release
模式下就是使用AOT
,此时,直接运行机器码
- Flutter 在发布时,可以通过
Flutter 高刷新率:120 fps
- 概述:
- Flutter 宣称,能在一秒中刷新120 张图片;
- 人眼在15 fps 就觉得很流畅了,游戏一般在30 fps以上;
- 为了保证快速的用户体验,需要能够在每个动画帧运行大量代码,不能有周期性的停顿,否则会造成掉帧;
- Dart 语言:
- 单线程:
isolate
机制- 不需要锁,不存在数据竞争和变量状态同步,其也没有线程上下文切换带来的性能损耗和锁导致的卡顿
- 垃圾回收:多生代无锁垃圾回收器,专门为UI 框架中常见的大量
widget
对象创建和销毁优化。- 新生代中存放大量临时对象,此处会发生频繁垃圾回收;
- 回收不了的,其
gc 分代年龄
增加,满足条件后晋入老年代
- 单线程:
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/yd-flutter/3655.html