专栏首页Java帮帮-微信公众号-技术文章全总结转发 | 闲鱼公开多年 Flutter 实践经验

转发 | 闲鱼公开多年 Flutter 实践经验

简介

flutter-boot核心解决了混合开发模式下的两个问题:flutter混合开发的工程化设计和混合栈。那flutter-boot是如何解决的呢?

首先在工程化设计的问题上,flutter-boot建立了一套标准的工程创建流程和友好的交互命令,当流程执行完成后,即拥有了混合开发的标准工程结构,这一套工程结构能够帮助我们同时拥有flutter和native(原生)两种开发视角,本地flutter开发和云端flutter构建两种flutter集成模式,其效果如图:

另外在混合栈的问题上,flutter-boot能自动注入混合栈依赖,同时将核心的混合栈接入代码封装后注入到原生工程内,在用户按提示插入简单几行模版代码后,即可看到混合栈的效果。 使用flutter-boot搭建的混合工程,开箱即可使用,接下来让我们了解下flutter-boot解决这些问题的详细过程。

开源地址

https://github.com/alibaba-flutter/flutter-boot

工程化设计

了解官方的Add Flutter to existing apps项目

在了解flutter-boot的工程化设计细节前,我们需要对Google官方提供的Add Flutter to existing apps方案有一个初步的了解。Add Flutter to existing apps项目会引导我们以module的形式创建flutter,module形态的flutter的工程结构如下:

some/path/
  my_flutter/
    lib/main.dart
    .ios/
    .android/

在官方的工程结构下,.ios和.android是运行flutter时的模版工程,在flutter工程目录下运行时即通过这两个工程来启动应用。那我们如何让原生工程和产生关联呢?这里的关联会分成三个部分,分别是flutter的framework,flutter的业务代码,和flutter的插件库。其中flutter插件库分成 flutter plugin native(即插件原生代码)和flutter plugin dart(即插件的dart代码)两个部分。这四部分的差异在于:

因此flutter framework只需要在依赖管理中声明即可,flutter plugin native可以直接以源码的方式集成,flutter plugin dart只有在被业务代码引用时才有效,因此和业务代码一样,需要支持dart代码的调试模式和发布模式,因此dart代码的关联会侵入到app的构建环节,根据app构建的模式来决定dart代码的构建模式。

具体的实现,拿iOS来举例,我们会在podfile文件中增加一个自定义的ruby脚本podfilehelper的调用,podfilehelper会声明flutter framework的依赖,声明flutter plugin native的源码引用,同时声明业务代码的路径。接下来会介入构建流程,在xcode的build phase内加入shell脚本xcode_backend的调用,xcode_backend会根据当前构建模式,来产出dart构建产物。

flutter-boot的补充

对于官方的混合工程项目,我们在体验后发现有如下的问题:

1. 文件或配置的添加为手动添加,流程较长。

2. 不支持在flutter仓库下运行原生工程。

3. 不支持flutter以独立代码仓库部署时的远端机器构建。

因此在flutter-boot脚手架中,为了解决这些问题,我们把混合工程的部署分为create,link,remotelink,update四个过程。

★ create

create过程目的在于帮助我们搭建一个flutter module,包括flutter module的创建和git仓库的部署,flutter module创建命令调用前,我们会做基础的检查来让工程位置和命名的规范满足官方的条件。在git仓库部署时,我们会在gitignore中忽略部分文件,同时我们会对仓库的状态进行检查,在仓库为空时,直接添加文件,在仓库非空时,会优先清理仓库。

★ link

link过程目的在于关联本地的原生工程和flutter工程。关联的过程中,我们会先请求获取flutter工程的地址和原生工程的地址,然后我们将上面提到的需要手动集成的部分通过脚本的方式自动集成;为了获得flutter开发视角(即flutter工程下运行原生工程),我们将原生工程进行了软链接,链接到flutter工程的ios目录和android目录,flutter在运行前会找到工程下的ios或android目录然后运行,在flutter工程下运行iOS工程会存在一个限制,即iOS工程的target需要指定为runner,为了解决这个问题,我们将原生工程的主target进行了复制,复制了一份名为runner的target。

同时,为了支持远程构建的模式,我们flutter仓库本地路径的声明根据构建模式进行了区分,封装在自定义的依赖脚本中,例如在iOS工程内,我们会添加fbpodhelper.rb脚本文件。然后将flutter仓库本地路径添加到了配置文件fbConfig.local.json中。

★ remotelink

update remotelink过程目的在于远端构建模式下,能够获取flutter仓库的代码,并在远端机器上进行构建。在远端构建模式下,我们会侵入依赖管理的过程,在依赖获取时,拉取flutter仓库的代码,将代码放置在原生工程的.fbflutter目录下,并将该目录声明为flutter仓库本地路径,拉取flutter代码并进行本地部署的过程,我们称之为update过程。

这样在远端构建时就能和本地构建如出一辙。 那远端模式和本地模式如何区分呢?为了区分远端模式与本地模式,我们将远端的flutter仓库信息记录在fbConfig.json,同时在gitignore中忽略fbConfig.local.json文件,这样只需要初始化混合工程的工程师运行一次remotelink,其他的开发协同者将不用关注远端构建的配置流程。

★ init

为了方便快速搭建,我们提供了一个命令集合,命名为init,我们将必备的环节以命令行交互的模式集成在了init命令中。

混合栈

混合栈是闲鱼开源的一套用于flutter混合工程下协调原生页面与flutter页面交互的框架,目前是混合开发模式下的主流框架。在混合栈开源后,我们关注到大量开发者在集成混合栈时会产生各种环境配置或代码添加导致的集成问题。因此我们决定提供一套快速集成的方案。要做到快速集成我们面临两个问题:

1. flutter和混合栈的版本兼容;

2. 混合栈demo代码封装及插入。

版本兼容问题

目前混合栈发布版本为0.1.52,支持flutter 1.5.4。当flutter升级时混合栈势必要进行适配,即我们集成的混合栈版本也需要变更。因此我们将混合栈的版本配置通过文件进行维护,记录当前flutter所需要的混合栈版本。在初版的flutter-boot中,我们限定了混合栈的版本号,在新版本混合栈发布时,我们将开放版本选择的功能。

代码封装及插入问题

在调研了混合栈的使用过程后,我们将混合栈需要的demo代码分成了四个部分:

1. flutter引擎的托管;

2. 页面路由的配置 ;

3. demo形式的dart页面 ;

4. 原生的测试跳转入口。

★ flutter引擎的托管

引擎的托管我们依赖于应用的初始化,由于初始化过程随着应用的复杂程度提升而提升,因此目前我们提供了一行代码作为接口,使用者在应用初始化时加入这一行代码即可完成托管。

★ 页面路由的配置

demo形式的dart页面,路由配置即路由到某个标识符时,flutter或原生页面需要识别并跳转相应页面。路由的配置需要在原生和flutter两侧进行部署。在原生侧,我们将混合栈的demo路由代码进行了精简,然后添加在了原生工程的固定目录下。由于iOS仅添加代码文件是不会被纳入构建范围的,因此我们封装了一套iOS侧的代码添加工具来实现文件的插入。在flutter侧我们对main.dart文件进行了覆盖,将带有路由逻辑的main.dart集成进来,同时提供了demo dart页面的创建逻辑。

★ 原生的测试跳转入口

为了方便使用者快速看到混合工程的跳转模式,我们在iOS和android双端封装了一个入口按钮和按钮的添加过程,使用者在测试的页面手动加入一行代码,即可看到跳转flutter的入口。

效果

在使用flutter-boot前,开发者可能要花费数天来进行混合工程搭建,现在,使用者只需要调用一个命令,加入两行代码即可完成混合工程的搭建,大大降低了开发者的开发成本。但flutter-boot的使命还未达成,我们期望使用者能更加流畅的进行flutter开发,未来我们会优化多人协同的开发流程,完善持续集成环境的搭建,让使用者拥有更佳的开发体验。

本文分享自微信公众号 - Java帮帮(javahelp)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Java提高十二】hashCode()equals()

    hashCode的作用 要想了解一个方法的内在原理,我们首先需要明白它是干什么的,也就是这个方法的作用。在讲解数组时,我们提到数组是java中效率最高的数据结...

    Java帮帮
  • 在 java 项目中使用 vicrab 实现自动化异常(BUG)管理插件

    系统错误异常管理是非常重要的系统模块,在我们的日常开发,测试,线上运营诊断都有着非常强大的做用。然而,传统的日志系统都是发生在系统出问题的时候,工程师们去后台一...

    Java帮帮
  • 【Java提高五】使用序列化实现对象的拷贝

    【Java提高五】使用序列化实现对象拷贝 我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能...

    Java帮帮
  • Flutter基础篇(7)-- Flutter更新错误全面解决方案(图文+视频讲解)

    (我电脑里面已经安装flutter最新版了。为了演示flutter升级过程,我删除了flutter文件夹,重新去github下载flutter文件,并且执行更新...

    AWeiLoveAndroid
  • Flutter单引擎和外接纹理内存优化探索之路

    今年九月初,王者人生Android端及iOS端正式接入flutter跨平台方案来提升开发效率。

    brzhang
  • 现有项目集成flutter排坑指南

    1、如果选择,stable,我们遇到的情况是,IOS上接入之后是跑不了的。切到master上就OK了。

    brzhang
  • 不得不看的Flutter与Android混合开发

    记得在flutter刚出来时,笔者就开始学习flutter。但由于当时嫌弃flutter复杂的层级组合且未推出稳定版,所以当时就放弃了深入学习,现如今随着flu...

    Android技术干货分享
  • Flutter 更新&升级

    https://flutter-io.cn/posts/announcing-flutter-1-7-9.html

    林小帅
  • flutter-Mac系统下安装之export PATH=`pwd`/flutter/bin:$PATH

    在执行export PATH=pwd/flutter/bin:$PATH命令的时候踩了一会儿坑,按教程执行完之后,在命令行输入 flutter doctor之后...

    coderZhen
  • Flutter开发:运行项目提示flutter packages get不成功的解决方法

    今天端午节,为了欢度佳节,就算再困也得起床发一篇博文,发完继续睡,顺便祝各路粉丝端午节快乐。

    三掌柜

扫码关注云+社区

领取腾讯云代金券