京东技术中台的Flutter实践之路

  • Android端动态化支持: 在Android端实现了动态化支持,可以线上热更新业务。iOS端暂不支持动态化。

目前京东商城、京东视频、京东到家、京东物流、7Fresh等APP都有业务采用JDFlutter进行开发。

JDFlutter框架设计

JDFlutter整体的框架结构,主要包含:基础框架、组件、工具三部分,如图所示:

基础框架

JDFlutter基础框架分为三层架构,包含JDFlutter基础层,通用业务层,业务层。

  • 基础层:提供了Flutter的基础组件支持,包括组件管理,状态管理等;基础层完全独立,对业务没有依赖。

  • 通用业务层:提供了通用型业务组件支持,例如登录组件,支付组件等;通用业务层依赖于基础层。

  • 业务层:即具体业务逻辑实现层,根据业务需要进行不同组件的组合,实现业务页面的快速开发。

核心组件
  • 组件管理:组件之间通过标准的协议接口进行通信,降低组件耦合,便于维护及组件升级;

  • 状态管理:实现数据和界面分离,统一状态管理,以数据的变化来驱动界面的改变,更有利于数据的持久化和保存,同时也有利于UI组件的复用;

  • Hybrid Router:主要解决Flutter和Native之间交叉跳转的问题,减少内存开销,共享同一个Flutter Engine。

工具介绍
  • 编译发布:优化Flutter原有的编译逻辑,管理依赖Flutter原生依赖关联,打包Flutter和原生代码,实现自动化构建发布。

  • 资源管理:管理图片资源,将资源转换成Flutter类,便于资源的读取操作,类似Andorid的R类;

  • 模版代码生成:减少Flutter的代码编写,自动生成Flutter 组件的框架模板代码,提升代码编写效率;

  • JSON转换:将JSON数据转换成Flutter code,并提供json转Flutter对象的API,减少动手编写Flutter code及解析。

JDFlutter业务开发实践

JDFlutter为业务研发团队提供了全流程的开发解决方案:

配置混合工程

Flutter和原生混合开发有两种情况,其一,开发Flutter业务的同学,需要和原生做交互,因此需要有Flutter和原生的混合编译环境;其二,使用原生SDK开发业务的同学,需要和Flutter业务一起集成打包,此时需对Flutter透明,以减少对Flutter编译环境的依赖,并且,只依赖原生编译环境即可,此时我们将Flutter编译成aar依赖,放入原生项目中即可。接下来,我们将重点介绍Android和iOS的混合编译环境配置。

Android平台配置

创建一个flutter module

flutter create -t module --org com.example my_flutter

在原生根项目的settings.gradle加入如下配置信息

// MyApp/settings.gradle

include ‘:app’ // assumed existing content

setBinding(new Binding([gradle: this])) // new

evaluate(new File( // new

settingsDir.parentFile, // new

‘my_flutter/.android/include_flutter.groovy’ // new

))

在原生App模块中加入flutter依赖

dependencies {

implementation project(‘:flutter’)

}

这样就可以原生项目一起编译了。具体可以参照官方文档:http://github.com/flutter/flu…这样的方式虽可以满足混编需求,但还不是特别方便,开发完项目后,还需要去Android Studio项目中进行编译,比较麻烦,所以我们也可以把Flutter项目settings.gradle改造,在Flutter开发环境下直接运行包含原生代码的混合项目,改造方式如下

// MyApp/settings.gradle

//projectName 原生模块名称

//projectPath 原生项目路径

include “:$projectName”

project(“: p r o j e c t N a m e " ) . p r o j e c t D i r = n e w F i l e ( " projectName").projectDir = new File(" projectName").projectDir=newFile("projectPath”)

这样改造之后即可在Flutter IDE中直接编译Flutter混合工程,并进行调试,也可以运行futter run来启动Flutter混合工程,不过在配置的时候,需要注意Flutter中 gradle编译环境和原生编译环境的一致性,如果不一致可能会导致编译错误。

iOS平台配置

创建flutter module

flutter create -t module my_flutter

进入iOS工程目录,初始化pod环境(如果项目工程已经使用Cocoapods,跳过此步骤)

pod init

编辑Podfile文件

#在Podfile文件添加的新代码

flutter_application_path = ‘/{flutter module目录}/my_flutter’

eval(File.read(File.join(flutter_application_path, ‘.ios’, ‘Flutter’, ‘podhelper.rb’)), binding)

安装pod

pod install

打开工程(***.xcworkspace) 配置build phase,为编译Dart 代码添加编译选项打开iOS项目,选中项目的Build Phases选项,点击左上角+号按钮,选择New Run Script Phase,将下面的shell脚本添加到输入框中:

“$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh” build

“$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh” embed

搭建PUB私服仓库

Flutter开发中使用的组件,一般公司内部会采用共享的方式,以避免重复开发,而Flutter组件共享,即需要使用pub仓库。由于公司内部的业务组件不适合上传到pub官方仓库,因此,需要搭建私服仓库,以解决各个业务研发团队,对Flutter组件共享需要。感兴趣的同学可以研究下官方pub仓库的源码 http://pub.dartlang.org/,其对Google Cloud 环境有很大的依赖 , 也可以基于https://github.com/kahnsen/pub_server来搭建一个简易版本的私服仓库,以满足上传和下载功能,pub协议相对比较简单,我们可以在源码增加协议接口来实现更多功能。运行pub_server

~ $ git clone https://github.com/dart-lang/pub_server.git
$ cd pub_server

~/pub_server $ pub get

~/pub_server $ dart example/example.dart -d /tmp/package-db

Listening on http://localhost:8080

To make the pub client use this repository configure your shell via:

$ export PUB_HOSTED_URL=http://localhost:8080

发布一个Flutter组件需要修改 pubspec.yaml,增加以下内容:

name: hello_plugin //plugin名称

description: A new Flutter plugin. //介绍

version: 0.0.1//版本号

author: xxx xxx@xxx.com//作者和邮箱

homepage: https://localhost:8080 //组件的介绍页面

publish_to: http://localhost:8080//仓库上传地址

上传时可以使用如下命令检查代码错误,并显示出上传的目录结构。

pub publish --dry-run

如果有不想上传的文件,可以在根目录增加一个.gitignore文件来忽略如下:

/build

Flutter组件的依赖配置,在项目的pubspec.yaml中dependencies:下增加如下信息:

dependencies:

hello_plugin:

hosted:

name: hello_plugin

url: http://localhost:8080

version: 0.0.2

这样可以在公司内部实现Flutter组件共享,如果不想搭建自己的pub仓库,也可以采用git依赖,配置如下:

dependencies:

hello_plugin:

git:

url: git://github.com/hello_plugin.git //git地址

ref: dev-branch //分支

Flutter业务的开发与调试

在Flutter IDE中编译代码调试会很方便,直接点击debug按钮即可进行代码调试,如果是混合工程在Android studio或者xcode中运行的工程,则没办法这么做,但也可以实现调试:将要调试的App安装到手机中(安装debug版本),连接电脑,执行如下命令,同步Flutter代码到设备的宿主App中

$ cd flutterProjectPath/

$ flutter attach

执行完命令后会进行等待设备连接状态,然后打开宿主App,进入Flutter页面,看到如下信息提示则表示同步成功

zbdeMacBook-Pro:example zb$ flutter attach

Waiting for a connection from Flutter on MI 5X…

Done.

Syncing files to device MI 5X… 1.2s

🔥 To hot reload changes while running, press “r”. To hot restart (and rebuild state), press “R”.

An Observatory debugger and profiler on MI 5X is available at: http://127.0.0.1:54422/

For a more detailed help message, press “h”. To detach, press “d”; to quit, press “q”.

打开http://127.0.0.1:54422可以查看调试信息,如有代码改动可以按r来实时同步界面,如果改动没有实时生效可以按R重新启动Flutter应用。

JDFlutter热更新实践

大部分跨端框架,诸如React Native / Weex / H5等,基本都能做到随时进行热修复,并随时上线,用于及时修复突发的在线问题,架构非常灵活。Flutter因其AOT的设计,预想会很难达到这种灵活度,但技术上仍具有一定的可行性,正如我们在之前的Flutter介绍文章中提到的,按照先有的API设计,是可以支持热修复的,但仅限于Android。官方最新的架构上已经支持了热修复架构,大家可以更新到1.2.1版本查看,但是官方的功能还比较弱,无法做到版本控制和回滚的灵活性,所以JDFlutter并没有采用。我们可以首先一起看一下Google官方热修复方案的设计原理:Flutter1.2.1 版本引入了 Dynamic Patch

为了更清楚的了解官方热修复的原理和过程,我们需要首先深入了解Flutter的业务包结构和整体运行过程:

Flutter App的包结构

可以看到主体代码集中在asset目录中,除此之外还有少量Android端的框架java代码及flutter so引擎库外:

1、icudtl.dat

2、isolate_snapshot_data

3、isolate_snapshot_instr

Flutter包的初始化流程

Flutter页面启动时是如何加载这些代码的呢?那就要从Flutter的初始化说起了,在页面启动前需要调用FlutterMain.startInitialization来做初始化:

可以看到该初始化是要求在主线程完成的,另外主要完成了以下三点:

  • 配置了一些环境数据,比如各个核心包的路径,主要是提供给其他一些模块全局调用

  • 检查 asset 下 Flutter 包的完整性,主要是上面介绍的一些核心包,一旦缺少核心的一些库,就会直接抛异常。开发过程中我们经常因为配置导致有些文件没有打包进去,然后会直接 crash,就是在这里触发的,具体代码如下:

  • 解压部分 asset 下的资源到 data 分区,以下是一些片段的代码,那为什么要解压呢?放在 asset 下也是可以通过 assetManager 读取的。这里 google 应该是从性能角度要求解压的,因为频繁的使用 assetManager 读取 asset 是很容易造成多线程阻塞的,一旦阻塞了将会导致整个 Flutter 业务全部无法渲染,所以需要解压一些核心的资源库,而不是解压了所有的资源 (例如图片就没有解压)

从代码来看,先增加要解压的核心库的目录,然后启动 task 从 asset 中解压库到 data 分区对应 app 数据下的 app_flutter 目录,以下是解压后的目录结构:

先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!!!!

尾声

在我的博客上很多朋友都在给我留言,需要一些系统的面试高频题目。之前说过我的复习范围无非是个人技术博客还有整理的笔记,考虑到笔记是手写版不利于保存,所以打算重新整理并放到网上,时间原因这里先列出面试问题,题解详见:


展示学习笔记

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可免费领取!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!!!!

尾声

在我的博客上很多朋友都在给我留言,需要一些系统的面试高频题目。之前说过我的复习范围无非是个人技术博客还有整理的笔记,考虑到笔记是手写版不利于保存,所以打算重新整理并放到网上,时间原因这里先列出面试问题,题解详见:

[外链图片转存中…(img-HBOFOfi7-1711253795838)]
展示学习笔记
[外链图片转存中…(img-ySgh8RaE-1711253795838)]
[外链图片转存中…(img-b3kfh9Vc-1711253795838)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可免费领取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值