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

Flutter新锐专家之路:工程研发体系篇

作者:闲鱼技术-正物写在前面当前,闲鱼客户端已经实现了基于Flutter的商品详情页的全量重构,线上效果良好。从alpha一路走来,我们遇到了很多问题,或基于原理,或透过社区,或与

作者:闲鱼技术-正物

写在前面

当前,闲鱼客户端已经实现了基于Flutter的商品详情页的全量重构,线上效果良好。从alpha一路走来,我们遇到了很多问题,或基于原理,或透过社区,或与官方合作,都一个个解决了,是时候梳理和总结下,也希望为其他的开发者们,尤其是已有工程中引入Flutter(混合场景)实现渐进式重构带来启发和帮助。
鉴于存在多个问题一个原因或解法的情况,而本系列的重点在于说明各种问题的解决方案与思路,就不一一列出问题。所有调试/热重载相关的Flutter均为Debug模式的Flutter,不再特殊说明。

本系列文章包含三篇:引入篇,运行篇,上线篇。引入篇重点介绍工程研发体系;运行篇介绍混合情景下的栈管理与能力补齐等;上线篇介绍兼容/稳定性保障及方法。

工程研发体系的关键点包括:

a.混合工程下的Flutter研发结构

混合工程中一个全局视角的的研发结构如何。

b.工程结构

已有的Native工程如何引入Flutter,工程结构如何组织,如何管理Flutter环境,如何去编译构建,集成打包等。

c.构建优化

这里主要介绍如何去针对Flutter的工具链(flutter_tools,Intellij插件等)进行调试与优化。

d.Native启动下的Flutter调试

不同于Flutter启动下的一体化调试,这种Native启动(Xcode/Android Studio启动,或点击图标打开应用)下的Flutter调试,我称之为分离式调试。分离式调试可以简化flutter_tools带来的复杂度,提高调试的稳定性和灵活性。

e.Native启动下的Flutter热重载

同d。

f.联合调试

即同时调试Flutter和Android/iOS。

g.持续集成

即混合环境下的Flutter构建与持续集成。

环境说明

Flutter新锐专家之路:工程研发体系篇

混合工程下的Flutter研发结构

Flutter新锐专家之路:工程研发体系篇

工程结构

这部分的核心逻辑是如何在最小改动已有iOS/Android工程的前提下运行Flutter。我们可以将Flutter部分理解成为一个单独的模块,通过pod库(iOS),aar库(Android)的方式,由CocoaPods和Gradle引入到主工程。

具体的原理与实践请参见:

深入理解flutter的编译原理与优化

Flutter混合工程改造实践

Add Flutter to existing apps

其中,我们将整套Flutter环境作为Git Submodule统一管理,以保证团队内环境一致,遇到的个性化的问题/需求能够统一处理。

Flutter新锐专家之路:工程研发体系篇

构建优化篇

编译速度的优化(Android)

问题:Android在由Flutter启动时构建缓慢。

原因:在flutter工具链(flutter_tools)的逻辑中,未找到android/app/build.gradle时,会运行gradle build从而执行多个编译配置的构建,而不是gradle assembleDebug。

解法:重构Android工程,使工程应用Module对应的build.gradle位于android/app下,从而符合flutter_tools的逻辑。

原理:flutter_tools的调试

a.修改flutter_tools.dart,使之可打印参数

Flutter新锐专家之路:工程研发体系篇

b.删除flutter/bin/cache/flutter_tools.stamp使得flutter_tools可以被重建

Flutter新锐专家之路:工程研发体系篇

c.从flutter运行构建,获取其入口参数

Flutter新锐专家之路:工程研发体系篇

d.用Intellij(或Android Studio下同)打开flutter_tools工程,新建Dart Command Line App,并基于步骤c获得的入参配置"Program arguments"

Flutter新锐专家之路:工程研发体系篇

e.开始你的flutter_tools调试之旅吧‘

Flutter新锐专家之路:工程研发体系篇

编译速度的优化(iOS)

问题:Flutter构建报"Observatory connection never became ready.",造成构建中断

原因:重构前我们的工程全量编译时间较长(1000+文件全量编译时长>10min),而Flutter Intellij插件有个超时逻辑,使得构建中断。

解法a(下策):定制Flutter Intellij插件(修改下面代码中的超时时间),编译插件,并替换Android Studio中的Flutter插件。更合理的解法是提PR,但这一路基本上都是在马不停蹄地解决各种产品化中的问题,所以...(最新版本已去除此逻辑)

原理:

前往查看Flutter Intellij源码

Flutter新锐专家之路:工程研发体系篇

事实上,我们使用IDE开发Flutter时,有下面的一个逻辑流程:

Flutter新锐专家之路:工程研发体系篇

解法b(中策):iOS工程的模块拆分和Pod(Framework)化,主工程构建依赖编译好的Framework,大大加快了构建时间。

原理:模块化+预编译Framework

解法c(上策):Native视角下的Flutter调试

原理:Native启动下,Flutter的调试与热重载

Native视角下的Flutter调试

Flutter启动下的Flutter的调试与热重载逻辑

实际上,当Native工程配置好Flutter支持后,Flutter启动下做的事情主要有:

a.检查是否需要重新生成flutter_tools.snapshot。

b.基于pubspec.yaml获取依赖(pub packages get),并生成插件描述文件.flutter-plugins和pubspec.lock。

c.基于Flutter配置(如Framework路径,Debug/Release模式,是否开启Dart2等),生成Generated.xcconfig(iOS)和local.properties(Android)。

d.基于gradle和xcodebuild构建应用(Flutter相关构建请参见前文中深入理解flutter的编译原理与优化)。

e.基于adb和lldb启动应用。

f.等待应用中Flutter启动,寻找Observatory端口,通过Dart Debugger连接以便调试。

g.寻找到端口后同步Hot Reload依赖的文件,同时透过Daemon监听命令(如用户点击插件按钮)实现Full Restart或Hot Reload。

换个角度来看,如果我们能够解决Native启动下的Dart调试和Hot Reload,由flutter_tools造成的编译慢等问题将不是问题,且可解决调试环境不稳定的情况(如我们的场景下,应用启动后,仅当用户点击进入详情页面的时候才会启动Flutter,此时flutter_tools才能去发现Observatory端口,调试和热重载,常有不好用的情况)。当从Xcode启动(或点击桌面图标启动,不再重复)包含了Debug模式Flutter内容的iOS(Android Studio启动Android类似,这里不再重复)应用时,我们需要关注abcfg。而abc除非flutter_tools或pubspec.yaml或Flutter配置变化等,否则都不需要重新执行。fg则是研发依赖的调试与热重载,必须考虑此模式下如何支持。

Native启动下的Flutter的调试与热重载逻辑

a.寻找iOS设备上Observatory端口

Flutter新锐专家之路:工程研发体系篇

或者命令行通过idevicesyslog获取,此处涉及到libimobiledevice库,其包含了idevicesyslog,iproxy等命令。

Flutter新锐专家之路:工程研发体系篇

可以看到iOS设备上Observatory启动了一个xxxx的端口(端口号随机)。

b.透过iproxy将iOS设备上端口xxxx映射到本机端口yyyy

Flutter新锐专家之路:工程研发体系篇

c.可以看到waiting for connection,此时就可以访问http://127.0.0.1:yyyy/#/vm打开Observatory如下:

Flutter新锐专家之路:工程研发体系篇

可以使用Observatory去检查诸多dart相关的内存,调试等,这里不展开。

也可以通过IDE链接去调试:

d.配置Dart Remote Debug

Flutter新锐专家之路:工程研发体系篇

这里需要注意的是端口要使用刚转发到电脑的端口yyyy,搜索源码路径是Flutter工程的根目录。

e.配置好之后点击Debug按钮,连接到调试端口

Flutter新锐专家之路:工程研发体系篇

f.成功后可以看到Debugger显示Connected(如果没有显示,再点击一次绿色的调试按钮‍️)

Flutter新锐专家之路:工程研发体系篇

g.之后便可以正常地使用IDE设置断点和调试dart(Flutter)代码

Flutter新锐专家之路:工程研发体系篇

Native视角下的Flutter热重载

a.启动App,进入Flutter页面,查找Observatory端口xxxx,并转发到电脑yyyy(同上面ab)

b.在Flutter工程目录下,执行flutter attach --debug-port=yyyy

Flutter新锐专家之路:工程研发体系篇

c.修改dart源代码,然后在b中Terminal中输入r(这一输入位于上图中'To quit,press"q"'之后)

Flutter新锐专家之路:工程研发体系篇

这里我们将超赞文案换成了赞。

d.可以看到Terminal显示"Initializing hot reload...Reloaded...",结束后,设备上变更生效(左下角文案变成了赞)

Flutter新锐专家之路:工程研发体系篇

Android下,Native启动的的Flutter调试/热重载类似iOS,不同的是获取端口时可通过IDE logcat或者adb logcat | grep Observatory,端口转发使用adb forward。

Native与Flutter联调

上文中已经介绍了如何在任意时刻(Flutter启动后)调试Flutter。此外我们还可以使用Android Studio的Attach Debugger to Android Process来调试Android,这就实现了Android与Flutter联调。同样,结合Xcode的Attach to Process,可以实现iOS与Flutter联调。

持续集成

目前团队包括Native同学和Flutter同学,因此我们区分了Flutter模式和Native模式。有一台公共设备(Mac Mini)安装了Flutter环境并负责Flutter相关的构建,构建好的产物以aar(Android)或pod库(iOS)的形式集成到Native工程下(可以认为Flutter相关的代码就是一个模块),用于构建最终产物apk(Android)或ipa(iOS)的CI平台最终也通过产物方式集成Flutter并打包。

更多细节请参见:

闲鱼flutter混合工程持续集成的最佳实践

写在后面

本文着重介绍了混合场景下的工程研发体系。解决这一问题后,接下来就要解决实际业务开发中遇到的问题。比如Native与Flutter互相跳转场景下的栈如何管理,Flutter不能实现的功能(平台特性等)如何去补全,Flutter Plugin/Dart Package包管理的方式有哪些等,这些敬请关注本系列的运行篇。

联系我们

如果对文本的内容有疑问或指正,欢迎告知我们。

闲鱼技术团队是一只短小精悍的工程技术团队。我们不仅关注于业务问题的有效解决,同时我们在推动打破技术栈分工限制(android/iOS/Html5/Server 编程模型和语言的统一)、计算机视觉技术在移动终端上的前沿实践工作。作为闲鱼技术团队的软件工程师,您有机会去展示您所有的才能和勇气,在整个产品的演进和用户问题解决中证明技术发展是改变生活方式的动力。

简历投递:[email protected]


推荐阅读
  • 本文详细介绍了git常用命令及其操作方法,包括查看、添加、提交、删除、找回等操作,以及如何重置修改文件、抛弃工作区修改、将工作文件提交到本地暂存区、从版本库中删除文件等。同时还介绍了如何从暂存区恢复到工作文件、恢复最近一次提交过的状态,以及如何合并多个操作等。 ... [详细]
  • flutter图片缓存Flutter的图片缓存机制有问题(可能是我使用的版本1.12.13有问题)网络图片会默认缓存到本地,但是不管图片是不是完整的或者损坏的,导致页面在下次进入的 ... [详细]
  • 基于,docker,快速,部署,多,需求,spark ... [详细]
  • 《Spring Boot开发:从0到1》大纲结构
    《SpringBoot开发:从0到1》大纲结构v2.0第一部分SpringBoot基础第1章SpringBoot史前简述1.1J2EE(Java2Pla ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • 本文介绍了使用readlink命令获取文件的完整路径的简单方法,并提供了一个示例命令来打印文件的完整路径。共有28种解决方案可供选择。 ... [详细]
  • 本文介绍了在Ubuntu系统中清理残余配置文件和无用内容的方法,包括清理残余配置文件、清理下载缓存包、清理不再需要的包、清理无用的语言文件和清理无用的翻译内容。通过这些清理操作可以节省硬盘空间,提高系统的运行效率。 ... [详细]
  • docker+k8s+git+jenkins
    docker+k8s+git+jenkins,Go语言社区,Golang程序员人脉社 ... [详细]
author-avatar
mobiledu2502898167
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有