简介: 离别高兴,祝你快乐~

作者:祈晴

  1. 闲鱼Flutter现状

===============

闲鱼是第一个应用Flutter混合开发的大型利用,但闲鱼客户端开发最深刻领会的痛点就是编译时长影响开发体验。在Flutter+Native这种开发模式下,Native编译速度慢,模块开发无奈冲破。闲鱼集成了团体泛滥中间件,很多性能无奈通过flutter间接调用,需应用各种channel到native去调用对应性能。总而言之,闲鱼目前Flutter开发面临如下几个痛点:

  • Flutter侧混合编译速度慢,Android首次编译10min+,iOS首次编译20min+
  • 混合栈编程中历史包袱导致IOS/Android双端返回给Flutter侧的数据可能存在不一致性
  • 集成模块开发效率相比模块开发较低,单模块页面测试性能数据无奈开展;

2.解决方案一

2.1计划概述

此我的项目从立项至今曾经很长一段时间,因为业务迭代快,native插件满天飞状况下,想要做到工程模块化拆分难度可想而知;如下图是我的项目立项为模块化拆分,业务方须要将各个业务拆合成耦合,拆分团体中间件,业务封装组件,Native业务代码,Flutter桥代码,Flutter组件库,Flutter侧业务代码等多个模块;我的项目初衷就是整顿代码,提供一个Flutter可运行的洁净环境,同时须要让flutter能够获取到native简直所有能力,然而编译开发调试时候有想要速度快,效率高。能想到的最间接解决方案就是拆包,从0-1建设一个最小壳工程,而后拆分团体根本中间件,封装业务组件,Flutter插件等,如下是整个我的项目架构:

日常模块化单页面级须要应用最小壳工程,其外部又channel的申明和实现,通过运行最小壳工程运行失去后果,Flutter侧模块开发通过IOC调用到最小壳工程的channel失去返回后果,最初将模块化开发以一种pub或者git依赖形式集成到闲鱼FWN主工程即可;

2.2 阶段性产出

业务模块化拆分素来都是一种吃力不讨好的活,明晓得拆出来有收益,然而投入产出比有余,因而历史包袱代码越来越厚重,以至于下一个接管的人都不敢轻易批改代码;在模块化拆分时候,开始我的项目时候提出过新起一个洁净的工程,而后一步步拆分团体中间件,期间拆出了Mtop/Login/FlutterBoost/UI Plugin,耗时3周/2人,失去局部后果就是新业务,新界面开发满足根本疾速迭代开发,毛病也很显著如下所示:

  • 拆分梳理Native的中间件繁琐,工作量微小,最小化壳工程耗时3周/2人
  • 推动业务方拆分根底组件库更难,目前我的项目停顿不顺
  • 保护老本高,拆分壳工程运行后果和主工程可能不统一
  • 业务迫切其后果,但投入产出比有余,比方Flutter单页面性能测试,Flutter侧模块化拆分,Fass工程一体基石

3.解决方案二

3.1 换位思考

(1)若本人是业务方,须要为Flutter侧去拆分包,去构建一个最小化壳工程,其老本是微小的。
(2)Fass工程一体化依赖一个最小化壳工程的Native运行环境去运行Flutter侧代码,可是并非所有的业务方都会提供一个最小化壳工程去运行Fass,那么Fass工程一体化/模块开发如果在团体其余运行环境下停顿?
(3)最小化壳工程运行环境无奈紧跟Native侧的各种版本,会导致运行后果不统一状况下也不敢轻易应用;

如果解决此问题呢?集体提出过跨过程实现形式,在Android端侧跨过程调用实现形式始终很常见的场景,client拜访server得后果,而Flutter侧和Native侧不就是client和server双端么?如下图所示,其实Flutter获取数据就是通过MethodChannel/EventChannel获取,因而能够换一种形式思考?

3.2 IPC跨过程通信,Android Binder

期间在Android侧我应用过Android Binder去实现,新起一个APP做为壳工程,其外部实现了各种插件去拜访主工程服务,获取后果而后返回给壳工程的Flutter调用,然而保护老本仍然在;同时iOS侧没有对应的实现机制,因而此形式被摈弃;

3.3 具体计划:Hook代理+Socket服务

Android开发应该都相熟hook和插件化技术,其实从之前的Flutter到Native的Chanel架构就能够想到一种思路,既然解决不了Native问题,那就解决Channel的问题吧,Native端侧的IPC形式无奈实现,换到Flutter侧和Native侧的Channel通信侧去实现IPC吧。参考业务对于插件化hook机制/IPC机制的了解,联合本身对于flutter channel的了解,能够实现一种利用socket服务去hook method channel和event channel实现形式,去代理客户端的method channel和event channel,将处理结果通过socket交给服务端去解决拿到服务端真正的method channel和event channel数据即可,这才是我心中想要的实现形式就是如此,整个架构图如下:

客户端是一台手机,服务端也是一台手机,服务端跑闲鱼FWN主工程,客户端跑一个洁净的Flutter工程;客户端先通过Flutter侧代码去找应用本端有对应的Channel,如果有则应用返回后果,如果没有则通过Socket申请后果到服务端主工程上,主工程依据Socket定义的协定字段去解析而后发动一个channel拿后果,之后通过socket将解决返回给客户端,客户端拿到了socket后果数据后执行想要的渲染形式即可;

或者你有质疑点:比方为什么要用2台手机,应用一台不能够么?
这里我举荐应用2台手机有如下2个起因:
(1)一台手机运行2个APP,如果server在后盾可能会导致过程资源被回收,Socket通信中断;
(2)应用2台手机有一个极大益处是,你运行Android的Flutter侧Client代码,然而往往你须要验证Native侧双端Server代码数据,如果客户端手机/服务端手机是2台,只须要改下客户端的IP地址去申请Android手机的Server还是IOS手机的Server就能够验证后果;

3.4 尝试验证

比方如下的method channel代码如下:

Future<T> invokeMethod<T>(String method, [ dynamic arguments ]) async {    assert(method != null);    final ByteData result = await binaryMessenger.send(      name,      codec.encodeMethodCall(MethodCall(method, arguments)),    );    if (result == null) {      throw MissingPluginException('No implementation found for method $method on channel $name');    }    final T typedResult = codec.decodeEnvelope(result);    return typedResult;  }

修复result == null的场景,如果是咱们指定的客户端,则通过socket去拿server数据,重点了解Fish MOD:START到Fish MOD:END代码思维就了解了;

Future<T> invokeMethod<T>(String method, [dynamic arguments]) async {    assert(method != null);    final ByteData result = await binaryMessenger.send(      name,      codec.encodeMethodCall(MethodCall(method, arguments)),    );    if (result == null) {      _//Fish MOD:START_      _//throw MissingPluginException(_      _//      'No implementation found for method $method on channel $name');_      _//socket从服务端手机获取值_      final dynamic serverData =            await SocketClient.methodDataForClient(clientParams);      _//Fish MOD:END_    }    final T typedResult = codec.decodeEnvelope(result);    return typedResult;  }

最初通过此中形式验证了MethodChannel/EventChannel数据失常收发的可行性,后续还须要在业务场景具体试验耕田;

4.后果比照和瞻望

后果比照:

无奈计划1和计划2最终都能够解决编译运行时长的问题,但计划1在拆分模块和保护模块时候都有很高的老本,运行时长尽管升高了,然而模块化工作量却加大很多,计划2能够完满解决拆分老本和保护老本,然而不足之处就是运行环境刻薄,可操作性有余,其须要2部手机作为运行环境,另针对于一些页面跳转逻辑,可能客户端手机A触发到服务端手机B上,操作性不在同一台手机上;当然计划二尽管有肯定缺点,却能够解决很多问题,因而后续在闲鱼模块化拆分落地我的项目中,在思考是否有更加完满的解决办法。

原文链接
本文为阿里云原创内容,未经容许不得转载。