MCube动态化与原生工程结合最佳实践

这篇具有很好参考价值的文章主要介绍了MCube动态化与原生工程结合最佳实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

跨端动态化开发方案重要性日益凸显,本文对我们团队MCube动态化实践做了总结,为大家提供经验和借鉴。

接入背景

随着我们工程的需求迭代,暴露出了业务需求量大,分端开发和发版更新成本高等痛点,使用H5页面来代替,在用户体验和性能相较原生有差异,所以我们团队开始了对动态化改造的研究。

在做过一些列动态化开发的尝试,并对多种方案进行调研后,我们选择了MCube的动态化方案。之所以选用MCube,是因为它有以下的优点:

1.方案成熟,对同为京东体系下的APP来说接入成本非常低,对照文档文档,整个接入的过程并不复杂。2.MCube有丰富原子组件,组件的灵活性非常高。

3.完善的组件市场可以很好的满足我们的需求。

4.一套XML模板适用多个平台,并且可以复用。

我们在接入的过程当中遇到兼容性问题,在沟通过程中,MCube的负责同学和开发人员积极性非常高,定制化开发的效率也很高,认真负责,有问必答,整个沟通过程非常愉快。

我们团队目前已经完成了从初步尝试,到一整个业务页面动态化改造的完整历程。期间遇到了许多问题,总结出了最佳化实践的经验,本篇文章做出总结,为其他已经接入和准备接入的同学提供经验。

单楼层动态化改造

虽然MCube的SDK提供了丰富的接口方法,但是为了方便使用和后续的全页面级别动态化控制,我们还是做了大量的封装和本地化开发。

首先,在数据层面:

根据MCube SDK的必传参数要求,我们封装了必要的module(页面名)和templateID(模版ID);在数据部分,模型封装了用于模版的数据源data,这样就可以让动态化视图(DYNContainerView)从数据源取数据进行展示,同时也方便外部下发;同时我们有大量原生楼层做动态化改造的场景,需要保留原数据进行交互和降级,所以模型预留了原生楼层使用的nativeData,方便在有以上需求的时候取用;最后,考虑到页面有将某些楼层按照section成组进行展示的场景,模型设计了用于组划分的groupID,相同groupID为一个section,按照页面具体的业务需求决定组的展示形式(卡片或者分割)。

在视图层面,以封装好的DynamicViewModel为基础,将动态化视图加载等操作进行了封装,形成了通用楼层CommonTableViewCell:

通用楼层的能力包括:

1.解析module和templateID

2.调用MCube SDK下载对应动态化模版,并在结束时给出回调

3.展示动态化视图DynView,使用数据进行刷新

4.支持设置降级视图,失败时进行降级

5.对于元素是原生视图的,通用楼层会用过layoutId将其找到,并通过Block回调出来,方便进行后续的操作,包括宽高调整,代理设置等等

self.successBlock = ^(DYNContainerView * _Nonnull dynamicView) {
    UIView *nativeView = [dynamicView getRrenderViewWithLayoutId:@"100"];
    if ([nativeView isKindOfClass:[原生视图类名 class]]) {
       //原生事件处理   
    }
};


全页面动态化改造

有了通用楼层,我们就开始了下一步的改造,最终的目的是实现全页面动态化下发,这也是我们团队对于动态化改造的新理解:全页面的所有楼层均支持动态化下发,原生楼层与动态化楼层共存,由数据来驱动,灵活控制楼层的展示形式,另外还可以由配置平台设置开关,控制动态化楼层的降级。

理想情况下,业务页面的顺序和楼层数据都可以由后端下发的数据源来决定。但实际进行改造的时候,我们时常会面对的情况是:后端下发的result里混杂着所有楼层的数据字段,每个楼层在加载数据model的时候要到result里单独找到自己要用的字段进行解析,这样就存在着两个弊端:

1.楼层顺序无法由下发控制

2.无法做到分楼层动态化控制

所以我们改造的第一步是对下发的数据结构进行重新定义。

"result":{
    "dynamicFloors":
        [
            {
                "type":"楼层类型",
                "module":"页面名",
                "templateID":"模版ID",
                "groupID":"part1"
                "data":{
                }
            }
        ]
}


我们设定了一个动态化楼层数组dynamicFloors,里面的每个元素代表了某一楼层的数据。type用于确定楼层类型,对于动态化楼层,会额外下发module和templateID,以此来区分动态化和原生楼层。如果发现下发了module和templateID,那么自动用DynamicViewModel来解析,将data设置进数据源,然后用CommonTableViewCell来加载和展示楼层。流程图如下:

后续可以推动服务端按照这个结构进行下发,当然,在推动其他团队同学改在之前,前端也可以先行对下发的result进行改造,但千万要保证数据安全并做好容错处理和降级开关。

改造成果:

踩坑Q&A

接入JDBDynamicModule后安装/编译报错

我们在接入的过程当中遇到了诸如类名和方法名冲突的问题,需要与MCube的相关负责人沟通,单独为工程进行SDK的定制化开发,解除依赖。

哪些楼层适合做成动态化楼层

就我们的经验来讲,适合做成动态化楼层需要满足以下一个或多个条件:

1.楼层的展示样式存在灵活变化的需求。

2.楼层的交互形式简单且单一。动态化着重于UI展示,相对来说模版交互事件开发较为繁琐。

3.安卓与iOS差异不大。这里的差异主要说的是模开发的差异,由于MCube本身的机制,在进行模版开发时经常会有安卓和iOS模版字段不通用的情况,具体见下面“安卓与iOS模版开发时的差异”部分。差异小可以保证安卓和iOS能采用同一套模版,减少开发工作量。

通过loadWithCallback加载模版失败

首先检查DYNContainerConfig对象的module和templateID是否设置正确。

其次检查是否实现了网络加载桥接类以及协议。MCube的所有网络请求都要经过桥接类来进行处理,走我们本地的网络请求并把结果返回给MCube。首先根据自己的命名需要创建一个类,并实现协议,在+load里对创建的类进行注册,主要是告诉MCube你的网络请求后续都由我这个类来处理

+ (void)load {
   [DYNMapperManager registeProtocolName:DYNProtocolConfig.networkProtocolName handlerClassName:NSStringFromClass(self)];
}


桥文件里的主要工作是实现协议里定义的相关方法,网络请求的DYNNetworkProtocol中主要需要实现的有:

getServerURL

根据自己的网络环境配置,返回MCube接口请求的URL头部,有两套:

1.正式环境:api.m.jd.com/XXX?functionId=

2.测试环境:beta-api.m.jd.com/XXX?functionId=

requestWithSetupModel: finish: cancel:

在这个方法里,需要创建API请求,将setupModel里的functionId和params,以及appType放进入参,发起请求,并把请求结果通过finish/cancel的Block回调返回给MCube进行处理。我们也可以在这里断点或者进行自己的处理,最主要的接口是获取模版列表,可以查看下发的模版列表文件是否正常。

getNetworkType

根据当前的网络环境返回网络类型,比如Wi-Fi,5G和4G等等。

模版中的ImageView图片无法加载

图片加载相关的请求也需要创建对应的桥接类,实现协议的相关方法。同时还需要给UIImageView创建一个category分类UIImageView+DYNBImageViewHandler,在分类里覆写dyn_setImageWithURL: placeholderImage:和dyn_setImageWithURL: placeholderImage: completed:方法,在它们里面利用sdWebImage等其他工具进行图片下载。

如何在模版中使用原生视图组件

MCube中可以将原生视图组件做为元素写到模版里,有以下步骤

1.原生视图组件实现协议里的两个方法:

#pragma mark - DYNCustomViewProtocol
- (id)getCustomView {
    return self;
}

- (void)setDataWithValue:(id)value object:(id)object sender:(DYNViewLayout *)sender {
    if ([value isKindOfClass:[原生模型 class]]) {
        //使用模型刷新原生视图组件
    }
}


2.在+load里声明模版元素与原生视图类的对应关系:

+ (void)load {
    [DYNMapperManager registeProtocolName:@"模版元素名" module:@"模块名" handlerClassName:@"原生视图组件类名"];
}



3.模版中用对应的元素名进行编写

<FlexboxLayout layoutId="999" width="match_parent" height="wrap_content" flexDirection="column" justifyContent="flex_start" bgColor="#FFFFFF">
    <模版元素名 layoutId="100" width="100%" height="100%" data="${原生模型对应key}" bgColor="#FFFFFF">
    </模版元素名>
</FlexboxLayout>

安卓与iOS模版开发时的差异

上文提到:由于MCube本身的机制,在进行模版开发时经常会有安卓和iOS模版字段不通用的情况,例如:

在我们的开发过程中,遇到的安卓和iOS不兼容的问题有:

1.安卓的嵌套滑动组件接入工程后,会报与本地的库有冲突。

2.FlexboxLayout 设置100%安卓可以滑动,ios滑动不了。

3.ImageView scaleType="stretch" 安卓会展示比例有问题,需要加useAspectRatio,ios没问题。

4.安卓在设置渐变色的时候语法不生效:

模版中如何做复杂的逻辑

1.数值结算

<ImageView height="$calc(44*SCREEN_WIDTH/375)" width="$calc(SCREEN_WIDTH)" />


2.条件判断

<ImageView src="@{${data.img1}?${data.img1}:${data.img2}}"/>
<View visibility="@{@{${data.show}!=null}?1:2}"/>


3.渐变色(拼接语法)

<FlexboxLayout bgColorList="$joint(${startColored},$unescape(comma),${endColored})">
<TextView text="$joint((${data.text1}  ${data.text2}))"/>

上传和发布模版

模版要上传到配置平台(具体网址请咨询相关负责人,并开通权限),在配置平台创建APP,模块(页面)和具体楼层,楼层可以发布不同版本,上传缩略图和模版文件,最后还可以选择白名单发布或者灰度发布。

如何做降级方案?

降级的形式我们在不同维度设立了三套方案:

视图层面

如果MCube的SDK加载动态化视图失败,会给我们一个失败回调Block,那么我们的处理是可以利用存在DynamicViewModel里的nativeData去加载原生楼层作为降级。

下发数据层面

可以通过控制是否下发module和templateID,来控制该楼层走原生展示还是动态化展示。

业务楼层层面

我们在配置平台设置了白名单(dynamicWhiteList)进行控制:按模块名(module)-模版名(templateID)来定位具体楼层,配置true(降级)/false(动态化)决定是否降级。

数据格式:

"dynamicWhiteList":{
    "页面名module":{
        "模版templateID 1":true,//降级
        "模版templateID 2":false//动态化
    }
}


作者:京东零售 姜海

来源:京东云开发者社区 转载请注明来源文章来源地址https://www.toymoban.com/news/detail-750426.html

到了这里,关于MCube动态化与原生工程结合最佳实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化

    动态内存管理的函数有:malloc,calloc,ralloc,free,本文讲解动态内存函数和使用,如何进行动态内存管理,实现通讯录联系人容量的动态化,对常见动态内存错误进行总结。                           ✨  猪巴戒 :个人主页✨                 所属专栏 :《C语言进阶》

    2024年02月04日
    浏览(67)
  • 从静态到动态化,Python数据可视化中的Matplotlib和Seaborn

    本文分享自华为云社区《Python数据可视化大揭秘:Matplotlib和Seaborn高效应用指南》,作者: 柠檬味拥抱。 首先,确保你已经安装了Matplotlib和Seaborn库。如果没有安装,可以使用以下命令进行安装: Matplotlib是一个灵活的绘图库,支持多种图表类型。以下是一个简单的折线图的

    2024年03月25日
    浏览(84)
  • GaiaX开源解读 | 跨端动态化模板引擎详解,看完你也能写一个

    GaiaX跨端模板引擎,是在阿里优酷、淘票票、大麦内广泛使用的Native动态化方案,其核心优势是性能、稳定和易用。本系列文章《GaiaX开源解读》,带大家看看过去三年GaiaX的发展过程。 在“GaiaX开源解读系列之第一篇:《GaiaX开源解读 | 基于优酷业务特色的跨平台技术》”中

    2023年04月08日
    浏览(35)
  • Soul 云原生网关最佳实践

    Soul 是基于兴趣图谱和游戏化玩法的产品设计,属于新一代年轻人的虚拟社交网络。成立于2016年,Soul 致力于打造一个“年轻人的社交元宇宙”,最终愿景是“让天下没有孤独的人”。在 Soul,用户可以无顾虑地表达自己,认知他人,探索世界,交流兴趣和观点,获得精神共鸣

    2024年02月02日
    浏览(39)
  • 云原生最佳实践系列2:基于 MSE 云原生网关同城多活

    分布在同城多个机房内的应用同时对外提供服务。同城机房物理距离较小,一般小于 50 公里。同城多活架构的难点有三个: 当某机房出现故障,能不能做到机房级的快速切换? 如何实现非对等部署下的全局的流量负载均衡? 对流量的精细化管控? 常见的同城多活实现方式

    2024年04月25日
    浏览(42)
  • 【ArchSummit】阿里云原生微服务架构治理最佳实践

      前言 📫 作者简介 :小明java问道之路,专注于研究 Java/ Liunx内核/ C++及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 📫 热衷分享,喜欢原创~ 关注我会给你带来一些

    2024年02月02日
    浏览(76)
  • 【云原生】-Zabbix6监控MySQL最佳实践

    📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10年DBA工作经验 一位上进心十足的【大数据领域博主】!😜😜😜 中国DBA联盟(ACDU)成员,目前从事DBA及程序编程 擅长主流数据Oracle、MySQL、PG 运维开发,备份恢复,安装迁移,性能优化、故障应急处理等。

    2024年02月02日
    浏览(59)
  • 云原生场景下高可用架构的最佳实践

    作者:刘佳旭(花名:佳旭),阿里云容器服务技术专家 随着云原生技术的快速发展以及在企业 IT 领域的深入应用,云原生场景下的高可用架构,对于企业服务的可用性、稳定性、安全性越发重要。通过合理的架构设计和云平台的技术支持,云原生高可用架构可以提供高可

    2024年02月07日
    浏览(90)
  • 编程之道:【软件工程实践】构建成功项目的最佳实践

    在现代软件开发中,采用最佳实践是确保项目成功的关键之一。软件工程实践涵盖了项目的各个阶段,从需求分析到设计、实现和测试。本文将介绍这些阶段的最佳实践,以帮助确保您的软件项目按计划成功完成。 1. 需求分析阶段 需求分析是软件开发的基石,因为它为整个

    2024年02月10日
    浏览(44)
  • 工程师常用的6种最佳实践

    一、约定大于配置 泰思勒定律也被称为复杂度守恒定律。该定律指出每一个过程都有其固有的复杂性,存在一个临界点,超过了这个点过程就不能再简化了,你只能将固有的复杂性从一个地方移动到另外一个地方。 根据这个定律,在做系统设计时,默认会给用户一个“套餐

    2024年02月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包