使用flutter跨平台开发 - 斗鱼APP

心动音符

前言

话不多说,直接上APP效果截图:(源码地址:https://github.com/yukilzw/dy...)

图片描述

图片描述

图片描述

图片描述

主要涵盖功能:

  • 滑动状态导航、轮播图
  • 移动端px兼容
  • 封装HTTP、IO缓存操作
  • 页面路由传值
  • bloc全局状态管理
  • 礼物横幅动画队列
  • 弹幕消息滚动
  • 接入静态视频流
  • 九宫格抽奖游戏
  • 照片选择
  • webView容器
  • ...

初识

flutter - 轻松、快速地构建漂亮的移动应用。

  • Flutter是Google使用Dart语言开发的移动应用开发框架,使用一套Dart代码就能构建高性能、高保真的iOS和Android应用程序,并且在排版、图标、滚动、点击等方面实现零差异。
  • 作为一个全新的移动端开发选择,谷歌希望日后为新系统fuchasia所使用(谷歌希望fuchasia能替代安卓系统,成为未来物联网多端集成的系统),因此在此之前同样支持在安卓、IOS上运行flutter,引导开发者技术转型。
  • flutter和前端的关系:flutter作为一种新的APP开发模式,和前端本质上没有任何关系(这一点和RN有本质区别),无论前端工程师还是安卓IOS工程师,面临的学习成本都是相似的。

详解

Flutter框架简介

上传成功

  1. 跨平台应用的框架,没有使用WebView或者系统平台自带的控件,使用自身的高性能渲染引擎(Skia)自绘,
  2. 界面开发语言使用dart,底层渲染引擎使用C, C++
  3. 组合大于继承,控件本身通常由许多小型、单用途的控件(Widget)组成,结合起来产生强大的效果,类的层次结构是扁平的,以最大化可能的组合数量

构建管道

上传成功

  1. 整合视图所有组件类的状态
  2. 通过继承自flutter基类的build方法,构建widget树,在任何状态改变的,重新触发build
  3. 根据传入每个widget的参数来计算样式,合并至渲染树
  4. 利用skia引擎在画布上进行重绘
  • 关于flutter渲染数据流相关的更详细分析,可查阅文章<br/>

flutter 原理

Flutter与React-native对比

架构设计差异

RN:
上传成功

Flutter:
上传成功

  • RN利用Bridge桥接的方式调用原生进行渲染,JSCore负责解析JS代码逻辑,映射到原生对应控件,由于安卓、IOS原生的差异性较大,RN底层需要对多端进行映射实现,并且难免出现不兼容情况。<br/>
  • Flutter利用skia引擎绘制渲染,直接与GPU交互,脱离系统层面,因此绘制出的UI可以完全一致,甚至可以用在web端(Flutter-web)。

用前端比较熟悉的WEB开发作比方,RN好比是构建DOM用浏览器内核解析渲染,而Flutter则类似canvas画布,在H5开发中,canvas绘制的图像由于是依赖GPU的像素点操作,不会有UI兼容性问题。

综上所述,flutter的性能的确做到完完全全等于原生,而RN在一些复杂业务场景下,会出现卡顿白屏。因此尽管RN诞生了快4年了,也没有复杂的APP使用纯RN开发,都是将RN当做热更新组件集成到现有原生APP。而Flutter不同,它就是一种APP开发方式,官方甚至没有给出集成到现有业务的方案(尽管此前美团通过修改Flutter打包逻辑做到了这一点,但是有点南辕北辙的意思)。

打包体积差异

上传成功

Q:从上表数据可以看出,在IOS下RN的体积要小的多,在安卓下Flutter体积要小的多,这是什么原因呢?

上面我们提到过,flutter需要skia引擎,这在安卓系统里是自带的(skia也是谷歌开发的东西),但是IOS里没这个玩意,所以打包的时候,需要吧C++编译后的代码也打到包里,无形中就增加了10M多。同理安卓系统JS引擎是V8,没有JSCore,所以RN打包安卓的时候,也要把JSCore打进去。但是不管是哪种方式,随着包的业务体积变大,引擎所占用的比例也就变得越来越小了。

  • 关于Flutter与RN的详细对比可以查阅:

全网最全 Flutter 与 React Native 深入对比分析

对比总结

  • Flutter性能会更好无线接近原生的体验,Dart是AOT编译的,编译成快速、可预测的本地代码
  • RN采用JS语言开发,基于React,对前端工程师更友好。Dart语言受众小,有学习成本
  • Flutter自己实现了一套UI框架,丢弃了原生的UI框架。而RN还是可以自己利用原生框架,两个各有好处。Flutter的兼容性高,RN可以利用原生已有的优秀UI
  • RN的布局更像css,而Flutter的布局更像native布局,但是去掉xml通过代码直接写需要适应下
  • Flutter的第三方库还很少,RN发展的早,社区环境逐步变得完善,Flutter github还有5000+个issues要解决

实践

最让大家关心的是如何利用flutter来开发一款APP,不幸的是,这对于前端工程师来说也许是一件不太友好的事,因为Flutter本身就不是设计给前端用的。

接下来会通过归纳学习路线,指引大家一步步的开发出自己的flutter应用,这个过程需要十足的耐心

Dart

第一步就是要学习Dart,这是一门2011年才由谷歌推出的新的编程语言,它是强类型、纯面向对象的。如果你对Typescript足够熟练,会降低Dart学习成本(作为前端开发者,建议先熟练掌握Typescript,这是必须的)。

推荐文档:<br/>

Dart 语法描述(中) - 来源于Dart中文网,顺着目录把所有语法看一遍

Dart SDK - Dart SDK 使用 API,也就是Dart虚拟机提供的底层类,比如网络、IO操作、异步等,类似于nodeJS中的net、fs、os等自带模块。

Dart PUB - 扩展的第三方模块,说白了,就是我们JS中的npm包,这是叫做pub,可以将自己封装的模块发到这个网址上,并且也有版本管理,和npm简直一模一样

中文版的内容有些删减,但是也覆盖了日常开发中所有的场景,如需要浏览全部API请查最新官方英文文档 Dart

flutter

搭建开发环境

如果搭建过RN环境,想必大家第一次都是各种报红,Dart在这方面更友好,只要要找官方指引走,基本上一次就能跑起来Hello Word

Flutter 搭建开发环境

总结一下顺序就是:

  1. 配置国内镜像到环境变量(有VPN当我没说...)
  2. 安装Flutter SDK(下载双击exe傻瓜操作)
  3. 将安装路径下 flutter\bin 文件夹配置到环境变量
  4. 安装 Android Studio并打开SDK Manage安装android SDK和android sdk build-tools

上传成功

<span style="color: red; font-weight:bold">如果之前使用过RN,可能已经安卓过SDK,但是版本并不一定适用,可以在cmd执行flutter doctor来检测当前环境是否搭建成功,如果有错误,根据提示安装对应版本SDK即可。</span>

上传成功

Android Studio的报错我们不管,我们用Vscode开发,我们只要关注第二项没红叉,这里警告是因为我的SDK版本是之前RN使用的,不完全符合,但这个版本不会出错没有红叉

  1. 安装VScode flutter插件
  2. 在一个目录下命令行执行flutter create myapp然后进入目录cd myapp
  3. 将你的手机插电脑,或者启一个虚拟安卓机,执行flutter devices检查是否有已连接设备
  4. 执行flutter run

看到一个Flutter APP界面出现在你的应用上,真是激动不已啊~

上传成功

应用的热更新 & 热重载

熟悉前端的同学都知道,在web开发时我们更新一段JS代码,页面不会刷新,会局部重载,而在业务结构改动的时候,热重载不会生效,必须进行刷新页面进行热更新,这得益于webpack-dev-server里webSocket的消息实现,在Flutter也有类似的功能,

当我们应用在cli里启动后,输入小写r触发热重载,输入大写R触发热更新。

上传成功

用VSCODE安装Flutter插件直接在根目录main.dart下按F5启动。

上传成功

上传成功

如果使用vscode内部插件启动flutter,需要点击编辑器上方的刷新按钮,根据个人喜欢选择启动方式

项目开发

在一切就绪后,我们开始进行编码,flutter的布局方式和WEB有着很大区别,没有层级样式表CSS,一切由Dart代码布局,通过为Widget注入参数来实现,但是由于Dart是强类型语言,远不如CSS灵活,每一种Widget都只允许注入指定参数,否则会编译报错,这就需要开发者对每一种Widget的用法都熟于心,这也增加了flutter的门槛。

布局由于是嵌套关系,但是flutter并没有HTML、XML、JSX这样的模板语法,纯粹由Dart类来构建视图结构,所以就出现了一个非常恐怖的问题 地狱嵌套,试想一下,如果大家用React的时候,不用JSX,而全部用Raact.createElement 嵌套children去实现dom树结构,然后将样式通过props中的style来设置,那这个代码有多可怕,但是flutter的写法就是这样的。

flutter 中文网来一步步学习flutter开发吧~

提供一个官方最全的虽有flutter API查阅文档f;utter SDK

调试

如果想要像chrome浏览器那样进行UI、断点调试,可以在VSCODE里安装官方工具Dart DevTools,这玩意用起来类似于chrome f12和react devtools,使用方法是在Vscode里F5启动flutter项目后,ctrl + p 输入:

上传成功

然后chrome会弹出调试界面:包含tree结构检查,元素审查,渲染性能,CPU,GPU,内存情况等等

上传成功

路由

APP的路由不存在url,因此路由都是动态的,不可能说我打开APP指定一个URL去唤起对应的某个页面,
在这个fluttergithub官方demo上有路由的实现方法,可以借鉴,但是没有给出传递参数的办法,我个人想办法用传参继承的方式做到了这一点,可参考dy_flutter

状态管理

在大型APP项目的开发中,如果仅仅使用StatefulWidget进行setState管理实例属性,无法满足要求,需要一种全局的状态管理手段,Flutter的状态管理方案的选择非常多样化,可以酌情选择:

  1. 直接使用flutter的InheritedWidget进行module状态管理 InheritedWidget数据管理,这种方式属于未封装的原生API,操作起来可维护性不强不做推荐
  2. 使用Redux,什么玩意?Redux?是的,国外的一个大佬用Dart语言基于InheritedWidgetAPI实现了一套flutter_redux库,不用多说了,就是anction+reducer+dispatch玩法,这是最适合前端的方案~~Flutter接入Redux
  3. ScopedModel 也是根据InheritedWidget继承实现的封装,API和redux不一样,不作赘述。
  4. Bloc(Bloc文档【英】),BLoc是一种利用reactive programming方式构建应用的方法,这是一个由流构成的完全异步的世界。更深层次的来讲,Bloc底层是基于RxDart的订阅观察者模式,RxDart是Rx设计的Dart语言实现,同类知名的还有RxJava,Rxjs,前者用在安卓应用状态管理,后者用在Angular前端框架状态管理。

视频流

目前使用官方插件video_player,但是只能支持播放静态视频,没有太好的直播流方案,还在研究

插件化

由于flutter 是自己绘制的UI层,不像RN或者Native那样可以直接调用系统功能(WebView、摄像头、陀螺仪)等,所以在真实业务场景下需要使用原生代码来实现插件给flutter调用。

总结

  • 本文对flutter的原理、搭建、学习路线等资料进行了一定的归纳,实际开发中会遇到各种各样的坑,有的是因为对flutter API不熟,有的甚至是因为flutter本身存在的一些问题。
  • 目前flutter仍处于发展探索阶段,离正式商业化使用还有距离,毕竟不可能将现有APP整个用flutter重构,现有APP接入flutter又是本末倒置,RN仍是跨双端开发更稳定的方案,使用于大多数场景,且JS + React的模式也更适合前端工程师。
阅读 7.7k

小王子的技术妖刀
积累,成长,分享,进步
856 声望
116 粉丝
0 条评论
856 声望
116 粉丝
文章目录
宣传栏