热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用flutter重构斗鱼APPdy_flutter

前言话不多说,直接上APP效果截图:源码地址:https:github.comyukilzwdy_flutter主要涵盖功能:滑动状态导航、轮播图移动端px兼容封装HTTP、IO缓

前言

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

使用flutter重构斗鱼APP - dy_flutter使用flutter重构斗鱼APP - dy_flutter使用flutter重构斗鱼APP - dy_flutter使用flutter重构斗鱼APP - dy_flutter

主要涵盖功能:

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

初识

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

  • Flutter是Google使用Dart语言开发的移动应用开发框架,使用一套Dart代码就能构建高性能、高保真的iOS和Android应用程序,并且在排版、图标、滚动、点击等方面实现零差异。

  • 作为一个全新的移动端开发选择,谷歌希望日后为新系统fuchasia所使用(谷歌希望fuchasia能替代安卓系统,成为未来物联网多端集成的系统),因此在此之前同样支持在安卓、IOS上运行flutter,引导开发者技术转型。

  • flutter和前端的关系:flutter作为一种新的APP开发模式,和前端本质上没有任何关系(这一点和RN有本质区别),无论前端工程师还是安卓IOS工程师,面临的学习成本都是相似的。

详解

Flutter框架简介

[外链图片转存失败(img-eAicPH8A-1568527893103)(https://ceph-dev-pub.dz11.com/fed-doc/1563345316987.png)]

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

构建管道

[外链图片转存失败(img-crK06E83-1568527893104)(https://ceph-dev-pub.dz11.com/fed-doc/1563346011910.jpg)]

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

    flutter 原理

Flutter与React-native对比

架构设计差异

RN:
[外链图片转存失败(img-SASPCsyd-1568527893104)(https://ceph-dev-pub.dz11.com/fed-doc/1563349953381.png)]

Flutter:
[外链图片转存失败(img-bPCit7gl-1568527893104)(https://ceph-dev-pub.dz11.com/fed-doc/1563350052318.png)]

  • RN利用Bridge桥接的方式调用原生进行渲染,JSCore负责解析JS代码逻辑,映射到原生对应控件,由于安卓、IOS原生的差异性较大,RN底层需要对多端进行映射实现,并且难免出现不兼容情况。
  • 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打包逻辑做到了这一点,但是有点南辕北辙的意思)。

打包体积差异

[外链图片转存失败(img-upircTxY-1568527893104)(https://ceph-dev-pub.dz11.com/fed-doc/1563348991175.png)]

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,这是必须的)。

推荐文档:

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

[外链图片转存失败(img-3NKcB6ei-1568527893105)(https://ceph-dev-pub.dz11.com/fed-doc/1563353803808.png)]

如果之前使用过RN,可能已经安卓过SDK,但是版本并不一定适用,可以在cmd执行flutter doctor来检测当前环境是否搭建成功,如果有错误,根据提示安装对应版本SDK即可。

[外链图片转存失败(img-GAHSxYkx-1568527893105)(https://ceph-dev-pub.dz11.com/fed-doc/1563354019502.png)]

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

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

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

[外链图片转存失败(img-vpcRgIRT-1568527893105)(https://ceph-dev-pub.dz11.com/fed-doc/1563354405160.png)]

应用的热更新 & 热重载

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

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

[外链图片转存失败(img-6cz79BVi-1568527893106)(https://ceph-dev-pub.dz11.com/fed-doc/1563354769695.png)]

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

[外链图片转存失败(img-WZWILBcz-1568527893106)(https://ceph-dev-pub.dz11.com/fed-doc/1563450951193.png)]

[外链图片转存失败(img-TRVV87kg-1568527893106)(https://ceph-dev-pub.dz11.com/fed-doc/1563449347577.png)]

如果使用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 输入:

[外链图片转存失败(img-b5WssLZ8-1568527893107)(https://ceph-dev-pub.dz11.com/fed-doc/1563451010955.png)]

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

[外链图片转存失败(img-l4aNbHA1-1568527893107)(https://ceph-dev-pub.dz11.com/fed-doc/1563451114381.png)]

路由

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的模式也更适合前端工程师。


推荐阅读
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 处理docker容器时间和宿主机时间不一致问题的方法
    本文介绍了处理docker容器时间和宿主机时间不一致问题的方法,包括复制主机的localtime到容器、处理报错情况以及重启容器的步骤。通过这些方法,可以解决docker容器时间和宿主机时间不一致的问题。 ... [详细]
  • 本文介绍了在Docker容器技术中限制容器对CPU的使用的方法,包括使用-c参数设置容器的内存限额,以及通过设置工作线程数量来充分利用CPU资源。同时,还介绍了容器权重分配的情况,以及如何通过top命令查看容器在CPU资源紧张情况下的使用情况。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
author-avatar
手浪用户2602915623
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有