美团外卖前端容器化演进实践( 三 )

由于这种格式是平铺分散的,没有将特定功能点的字段聚合在一起表示,不利于我们动态地将数据Model与Block绑定在一起 。
需要我们将一个模块的数据统一在一个JSON对象中,整理之后API数据返回的格式如下:
{ "data":{ "pay_by_friend":{//key "xxx_pay_by_friend": true, "xxx_by_friend_tip": "发给微信朋友,让TA买单", "xxx_by_friend_bubble_desc": "找微信好友买单", "xxx_friend_order": false } } "code":0, "msg":""}将平铺的API数据整理成定制的结构化数据,将Key作为唯一的标识,那么就可以方便地用来对应指定模块化Block中所需的数据Model 。
布局及位置信息会对应相应的模块视图层,这由另外的layoutInfo字段给出 。数组中的每条元素对应每一个Block模块 ,其中 native_id的值是唯一的且与上面Block在注册时候的Key保持一致,data_key的值映射上面整理之后的API数据的Key,这样在编译时期生成Block的时候,就可以动态地关联相应的ViewModel以及数据模型 。
{ "layout_info":[ {"native_id":"order_pay_by_friend","data_key":"pay_by_friend"}, { "native_id":"block_container_default",//容器组 "children":[ {"native_id":"order_flower_cake","data_key":"flower_cake"} ] } ]}当然,这里可以以组为维度将一些功能相似的模块聚合在一起,native_id的含义同上,Children是子Block结点的数组 。
4. 模块间通信问题
由于之前模块化的时候,我们通过中间类的方式承载各个业务模块的通信逻辑 。以Android为例,我们将多个子模块之间需要通信的逻辑,用接口的方式抛到Activity层,由Activity层进行业务逻辑的实现,但是由于子模块众多,最终导致该类的膨胀和模块的高耦合性,难以进行扩展和维护 。
在容器化设计的时候,为了更好地使各个业务之间进行通信,降低耦合性,我们引入了BlockContext,同上所述,理解为通信总线 。
每个Block都有自己的BlockContext,各个BlockContext汇总到Root Block Context中去实现,最终,各个Block就可以通过BlockContext进行数据传递 。
整体的通信分发图如下:

美团外卖前端容器化演进实践

文章插图
 
图中展示的两种数据方式
4.1 Command数据交互方式
将所需要的数据包装成事件,在指定的位置驱动事件的执行进而拿到需要的数据 。
//声明事件容器private SupplierCommand<Object> mSupplierCommand = new SupplierCommand<>();@Overridepublic SupplierCommand<Object> getSupplierCommand() { return mSupplierCommand;}//注册实现context().getSupplierCommand().registerCommand(new Supplier() { @Override public Object run() {}});//获取相应的Object对象context().getSupplierCommand().execute();4.2 Event数据交互方式
利用观察者的方式,订阅相应的事件,通过主动触发,从而完成数据分发等不同操作 。
//声明事件容器private SupplierEvent mSupplierEvent = new SupplierEvent();@Overridepublic SupplierEvent supplierResponseEvent() { return mSupplierEvent;} //实现订阅context().supplierResponseEvent().subscribe(new Action() { @Override public void action() { }});//触发相应的操作context().supplierResponseEvent().trigger();5. Block页面数据分发问题
5.1 数据分发问题
Root Block在接收数据的之后,会按照Block结点进行数据的分发 。父Block将数据逐次的分发给子Block 。
美团外卖前端容器化演进实践

文章插图
 
Block Tree数据分发逻辑简介图
 
美团外卖前端容器化演进实践

文章插图
 
Block页面的刷新流程时序图
5.2 Block创建的顺序
Block创建的顺序由API结构化数据中的layoutInfo数组来决定,layoutInfo数组的具体格式如第三节API数据结构化中内容所示 。容器化后的提单页会根据layoutInfo数组的顺序,依次创建对应native_id的Block模块 。因此,对于一些基础公共模块(比如wm_confirm_order_logical对应的Block),我们可以将其放在layoutInfo数组的最前面让其提前加载,保证负责UI展示的Block创建时数据可用 。
5.3 数据拉取问题
由于提单页的模块比较多,在页面曝光、页面刷新或提交请求时,需要从指定的模块获取相应的数据,作为请求的入参,那么如何做成在不感知其他业务方模块的情况下,完成数据的组装呢?
如上面的通信设计思路,我们利用Event数据交互方式,从各个模块中将需要的数据取出来,完成数据的拼装 。其中不同业务场景提取数据需要的校验工作,也分散在各个模块中进行处理 。最终,即使在物理层面上隔离了对Block的感知,但是依然可以完成对请求所需数据的获取 。


推荐阅读