为什么选择Flutter 进行跨平台开发

Flutter 初见

本文概述:

  • 文章以跨平台开发为背景,探讨了跨平台开发技术的发展历史,以及Flutter 的优势。
  • 思维导图:

学习跨平台技术的必要性

  • 传统移动端原生开发弊端:

    • 传统的原生开发需要维护Android 、IOS 两个平台;
  • 使用Flutter 进行移动端开发的优点:

    • Flutter 为跨平台的UI 框架,
    • 真正做到一套代码多端使用,增加代码复用,易维护;
  • 在于求职中,若具备跨平台开发能力,将具备更强的市场竞争力;

跨平台开发发展历史:

第一阶段:纯原生开发

  • 开发成本大:需要维护Android 与 IOS 两套代码;
  • 动态化需求:需求发生变化时,纯原生应用大多需要通过版本升级来更新内容。

    • 缺少热更新
  • 原生开发不可替代的优势:性能优势
  • 混合开发出现的原因:

    • 当硬件设备性能提升,反哺开发模式,即,可牺牲一部分性能使用混合开发,以减少开发成本。

第二阶段:基于WebView 的 PhoneGap & Cordova(H5 )

  • 出现时机:

    • 在20008 年提出 PhoneGap,其采用 HTML + CSS + JavaScript,依托于Android 内置WebView 实现混合开发,宣称接近原生性能。后衍生出Cordova,这个是从PhoneGap 中抽离出的核心代码,因为收购原因,所以改了名字,其实还是一套代码;
  • 技术现状:

    • 除了简单页面外,在考虑性能时,基本不会采用此种跨平台手段。
  • 底层机制:

    • 在Android 中使用WebView 加载 HTMLHTML传给 JS 一个JavaInterface, Js 通过传入的JavaInterface 进而调用到Android 上的代码。
    • 图示:

  • 核心代码:HTML 要与原生进行交互

    • Java 代码:使用WebView 加载 HTMLHTML传给 JS 一个JavaInterface
    webview.addJavaInterface(new AndroidPlatform(this),"android");
    • Js 代码:Js 通过传入的JavaInterface 进而调用到Android 上的代码。
    • 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();
        }
    }
  • 技术优点:

    • 结构较为清晰,写起来比较简单
  • 存在的问题:

    • 兼容性太差:因为手机厂商的不同,所以细节上的实现也不同
    • 渲染性能太差:加载HTML 非常缓慢

      • 并且HTML 中可能充斥过多JS 代码,而JS 可是解释型语言,其执行效率太差了。
      • 补充:Java 不是编译型也不是解释型

        • Java 先编译成 xxx.class文件,再交由虚拟机解释执行;但存在 JIT ,且Java9 引入了AOT
    • 内存泄漏: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 中绘图的底层,nativeJNI 代码就是用这个的,Chrome 浏览器中也是这个
    • 虚拟机就在这Engine 层

Flutter 发展历史

  • 发展历史:

  • 补充:Dart 语言的发展历史

    • 因为Google 内部对JS的不满,其开发出Dart语言,并在Chrome 浏览器中内置了Dart 虚拟机,为Dart 语言 提供了执行环境。由于Chrome 浏览器影响巨大,Dart 语言 也在前端开发中占据一席之地。
    • Node.js 出现又让Js 焕发第二春,其充斥前端、后端、移动端。甚至出现能被Js 实现的,终究会被Js 实现等。Dart 语言 也逐渐淡出大众视野,甚至Dart 虚拟机也被从Chrome 中移除了。

Flutter 特点:

  • 快速开发:热重载

    • 是什么:亚秒级修改,跟之前的instant run 类似

      • 但AS 提供的instant run 在修改UI 后,不用重新安装,即可查询到其安装在手机上后的真实效果;
      • 但是这个有点坑,基本上不用这个
    • 有什么用:节省反复安装、运行以测试的时间

      • 修改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 略高于原生开发

怎么判断一个App 是否是Flutter 开发的?

  • 以腾讯 Now 直播为例;

    • 将其解压后在lib 目录下,查看发现有libflutter.so 那么就是了;

      • Flutter 架构中的Engine 层就在这个文件
  • 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)
  • 基于 AOT 的发布包

    • Flutter 在发布时,可以通过 AOT 生成高效的 ARM 代码以保证应用性能;
    • Flutter 在Release 模式下就是使用 AOT,此时,直接运行机器码

Flutter 高刷新率:120 fps

  • 概述:

    • Flutter 宣称,能在一秒中刷新120 张图片;
    • 人眼在15 fps 就觉得很流畅了,游戏一般在30 fps以上;
    • 为了保证快速的用户体验,需要能够在每个动画帧运行大量代码,不能有周期性的停顿,否则会造成掉帧;
  • Dart 语言:

    • 单线程:isolate 机制

      • 不需要锁,不存在数据竞争和变量状态同步,其也没有线程上下文切换带来的性能损耗和锁导致的卡顿
    • 垃圾回收:多生代无锁垃圾回收器,专门为UI 框架中常见的大量 widget 对象创建和销毁优化。

      • 新生代中存放大量临时对象,此处会发生频繁垃圾回收;
      • 回收不了的,其gc 分代年龄 增加,满足条件后晋入老年代

你可能感兴趣的:(flutterandroid)