一、什么是跨平台,各方案对比
1.1、什么是跨平台
传统的纯原生开发已经不能满足日益增长的业务需求。主要表现在如下两个方面。
- 动态化内容需求增大。当需求发生变化时,纯原生应用需要通过版本升级来更新内容,但应用上架、审核是需要周期的,这个周期对高速变化的互联网时代来说是很难接受的,所以,对应用动态化(不发版也可以更新应用内容)的需求就变得迫在眉睫了。
- 业务需求变化快,开发成本变大。由于原生开发一般都要维护 Android、iOS两个开发团队,版本迭代时,无论人力成本还是测试成本都会变大。
总结一下,纯原生开发主要面临动态化和开发成本两个问题,而针对这两个问题,又诞生了一些跨平台的动态化框架。只需一处编写,各平台调用或打包
1.2、跨平台方案对比
针对原生开发面临的问题,人们一直都在努力寻找好的解决方案,然而时至今日,已经存在很多跨平台框架,本次特指 Android和iOS两个平台,根据其原理,主要可分为如下几类。
- H5(HTML5)+原生( Cordova、 Ionic、微信小程序、uniapp)
这类框架的主要原理是将APP需要动态变动的一部分内容通过H5来实现,通过原生的网页加载控件 Webview( Android)或 WK Webview(iOS)来加载。这样,H5部分就可以随时改变而不用发版,动态化需求得到满足;同时,由于H5代码只需要一次开发,就能同时在 Android和OS两个平台上正常运行,这也可以降低开发成本,也就是说,H5部分的功能越多,开发成本就越小。我们称这种H5+原生的开发模式为混合开发,对于采用混合模式开发的APP,我们称之为混合应用或 Hybrid APP,如果一个应用的大多数功能都是采用H5实现的话,我们称其为 Web APP。目前混合开发框架的典型代表有 Cordova、 lonic和微信小程序,值得一提的是,微信小程序目前是在 Webview中渲染的。并非原生渲染。
- Javascript开发+原生渲染( React Native、Weex、快应用)
这种最主要的就是RN(React Native),在React-native文件中编写的代码,会在内存中生成虚拟DOM对象(其实就是一个JS对象),然后再通过javaScriptCore(IOS自带,安卓不是,所以RN打包后安卓的包比苹果大)映射成原生控件树。很多jsBridge都是基于javaScriptCore实现的
Weex主要是阿里系在做
快应用是各大安卓手机厂商在做,已经凉了
- 自绘UI+原生( QT Mobile、 Flutter)
Flutter是google推出并开源的移动应用开发框架,主要特点是跨平台、高保真、高性能。开发者可以通过Dar语言开发APP,一套代码可以同时运行在OS和 Android平台以上。Flutter提供了丰富的组件、接口,开发者可以很快地为 Flutter添加 Native扩展。同时Flutter还可以使用 Native引擎渲染视图,这无疑能为用户提供良好的体验。Flutter有如下优点:
跨平台自绘引擎
Flutter既不使用Webview,也不使用操作系统的原生控件。相反, Flutter使用自己的高性能渲染引擎来绘制 Widget。这样不仅可以保证在 Android和iOS上UI的一致性,而且可以避免因对原生控件依赖而带来的限制及高昂的维护成本。
Flutter使用ska作为其2D渲染引擎,Skia是 Google的一个2D图形处理函数库,包含字形、坐标转换,以及点阵图,且都有高效能且简洁的表现,Skia是跨平台的,并且其还提供了非常友好的API,目前 Google Chrome浏览器和 Android均采用Skia作为其绘图引擎。
Flutter框架图如下:
分为业务层、UI框架层、引擎层、嵌入层
新的Weex 2.0框架改为自绘引擎,直接复用了部分Flutter Engine,Weex不看好,1.0仿RN,2.0仿Flutter
Flutter支持iOS、 Android平台。而且 Flutter也支持Web开发( Flutter for Web)和PC开发
Flutter自己有自己的渲染引擎,这样避免了以上几种跨平台技术的通过中间层通信带来的性能开销,但是依然避免不了写原生代码
高性能
Flutter的高性能主要靠两点来保证,首先, Flutter APP采用Dart语言开发。Dart在JIT(即时编译)模式下,速度与 Javascript基本持平。同时Dart还支持AOT,当以AOT模式运行时, Javascript便远远追不上了。速度的提升对高帧率下的视图数据计算很有帮助。其次, Flutter 使用自己的渲染引擎来绘制UI,布局数据等由Dart语言直接控制,所以在布局过程中不需要像RN那样要在 Javascript和 Native之间通信。特别是在滑动和拖动的场景下具有明显的优势,因为滑动和拖动的过程往往会引起布局发生变化,所以 Javascript需要与 Native不停地同步布局信息,这与在浏览器中要 Javascript频繁操作DOM所带来的问题是相同的,都会带来比较可观的性能开销
- 独立引擎+各平台支持(cocos2d,unity3d)
多用于游戏,如王者荣耀、炉石传说
1.3、Flutter相关资源
- Flutter官网:flutter.dev
- Flutter源码:github.com/flutter/flu…
- Flutter插件平台:pub.flutter-io.cn
- Flutter中文网:flutter.cn
三、Flutter开发配置
3.1、平台选择
目前跨平台主要是跨Android和iOS两端,考虑到iOS打包要用到xcdoe工具链,所以一般Flutter开发都在macOS环境
3.2、配置环境变量
export ANDROID_HOME=/Users/lag/Library/Android/sdk
export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
export PATH=/Volumes/ServerDevelop/flutter/bin:${PATH}
3.3、AndroidStudio配置
Flutter开发工具一般用AndroidStudio,也可以使用IDEA
配置装Android SDK, Android SDK Command-line Tools
安装Flutter和Dart插件
3.4、flutter doctor自检
ChengHaodeMac-mini:~ chenghao$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.3, on macOS 11.6 20G165 darwin-x64, locale
zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2019.3.2)
[✓] VS Code (version 1.63.2)
[✓] Connected device (2 available)
3.5、常见flutter命令
1.flutter doctor:检查flutter状态,很重要能知道自己环境配置的问题。
2.flutter emulators:获取模拟器列表(iOS、Android模拟器)
3.flutter devices:获取所有真机设备列表包括iOS模拟器
4.flutter run -d <deviceId>:运行指定模拟器或者真机
5.flutter run -d all:运行所有模拟器
6.flutter build apk:打包apk
7.flutter build ios:打包ipa
8.flutter help:查看命令的帮助信息
9.flutter create -h:创建项目
四、Flutter开发的五种场景
4.1、纯Flutter项目
包含Dart部分,包含单独的iOS和Android工程
在Android上安装直接AS运行即可
在iOS设备上运行需先在xcode中配置相关的证书
4.2、Flutter插件(Plugin)和 Fluuter包(Package)
Plugin只包含Dart代码的包,Package包含Dart和原生代码
Package 和插件 (plugin) 有什么区别呢? 插件 (plugin) 是 package 的一种,全称是 plugin package,我们简称为 plugin,中文叫插件。
Packages
Dart package 最低要求是包含一个 pubspec.yaml 文件。此外,一个 package 可以包含依赖关系 (在 pubspec.yaml 文件里声明)、 Dart 库、应用、资源、测试、图片和例子等。 pub.dev 上列出了很多 package,由 Google 工程师和 Flutter 和 Dart 社区的开发者开发和发布,你可以用在自己的应用里。
Plugins 插件 (plugin package) 是一种特别的 package,特别指那些帮助你获得原生平台特性的 package。插件可以为 Android (使用 Kotlin 或 Java 语言)、 iOS (使用 Swift 或 Objective-C 语言)、Web、macOS、Windows、Linux 平台,或其任意组合的平台编写。比如:某个插件可以为 Flutter 应用提供使用原生平台的摄像头的功能。
4.4、Flutter模块(Module)
原生iOS/Android项目内嵌Module
- iOS内嵌Flutter
- Android内嵌Flutter
4.5、Flutter模板(SKeleton)
从Flutter 2.5版本以后开始支持,该种方式就是为开发提供一种较好的项目模板,不在是默认的Couter app。 模板中可以看到路由、资源、多语言、状态管理,文件夹等好的实践方法。
五、Flutter的几个技术要点
5.1、 Dart语法及数据结构
Dart&Kotlin&Swift三种语言对比
变量和常量
Dart
var myVariable = 42;
myVariable = 50;
final myConstant = 42;
const myConstant2 = 'John';
Kotlin
var myVariable = 42
myVariable = 50
val myConstant = 42
Swift
var myVariable = 42
myVariable = 50
let myConstant = 42
可以看到,这三种语言很相似
三种语言都支持可空性&可选性
Dart (tested <= v2.7) Kotlin Swift
// 声明 // 声明 // 声明
int id = null; var id: Int? = null var id: Int? = nil
id.abs(); //异常 id.inc() // 编译错误 id.signum() // 编译错误
id?.abs(); // 安全的调用 id!!.inc() // 异常 id?.signum() // 安全的调用
// Null aware 操作符 // Elvis 操作符 // 空合操作符
int id = null; val id: Int? = null let id: Int? = nil
var userId = id ?? -1; var userId = id ?: -1 var userId = id ?? -1
// 可选型(还在实现中) // 可选型 // 可选型
int? id; // 需要启用实验特性 val id: Int? var id: Int? // 可选型
var userId = id ?? -1; var userId = id ?: -1 var userId = id ?? -1
// 编译错误:id 必须先被初始化 // 输出 -1
Dart官网:dart.dev
Dart中文网:dart.cn
5.2、多线程、网络
Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。
参考文章:www.jianshu.com/p/54da18ed1…
flutter 请求网络的方式有三种,分别是 Dart 原生的网络请求 HttpClient、第三方网络请求 http以及 Flutter 中的 Dio
参考文章:cloud.tencent.com/developer/a…
5.3、生命周期
Flutter跟安卓的Activity、iOS的ViewController一样拥有自己的生命周期, Flutter中一切都是Widget,渲染方式有点像H5的DOM树。
5.4、布局
Flutter 布局的核心机制是 widgets。在 Flutter 中,几乎所有东西都是 widget —— 甚至布局模型都是 widgets。你在 Flutter 应用程序中看到的图像,图标和文本都是 widgets。此外不能直接看到的也是 widgets,例如用来排列、限制和对齐可见 widgets 的行、列和网格。
以下是这个 UI 的 widget 树形图:
布局核心技术:增量渲染,所以同名widget要用到key来区分
5.4、热重载
Flutter 的热重载功能可帮助您在无需重新启动应用程序的情况下快速、轻松地测试、构建用户界面、添加功能以及修复错误。通过将更新的源代码文件注入到正在运行的 Dart 虚拟机(VM) 来实现热重载。在虚拟机使用新的字段和函数更新类之后, Flutter 框架会自动重新构建 widget 树,以便您可以快速查看更改的效果。
AOT\JIT
JIT:支持在运行过程中进行HotReload,刷新过程是一个增量的过程,系统会对上一次的代码做一个snapshot,将新的代码注入到DartVM中进行刷新
AOT:运行前预先编译好,这样在每次运行过程中就不需要进行分析、编译,此模式运行速度最快
Flutter同时采用这两种方案,开发阶段用JIT,release阶段采用AOT
六、Flutter仿写微信个人中心
- BottomNavigationBar
- 个人中心页面布局
- 访问原生相册,两种方式调用原生相册
- 和原生通信
- 第三方ImagePicker
七、总结
- Flutter能达到原生效果和性能
- Flutter是最有前景的跨平台方案
- Dart语法和Kotlin、Swift语法相似,布局和H5相似,学习起来很简单
- 离不开原生的支持