PCon全球产品创新大会最新日程上线,这里直达 了解详情
写点什么

有赞移动消息卡片动态化方案实践

  • 2020 年 8 月 08 日
  • 本文字数:3473 字

    阅读完需:约 11 分钟

有赞移动消息卡片动态化方案实践

概述

消息业务作为有赞移动的共享业务,在微商城、零售、美业等 B 端 App 中承担着多客服的角色,多客服是有赞为商家提供的连接商家和买家的即时消息客服工具;在精选、有赞客 C 端产品中扮演着用户联系商家的角色。在整个有赞产品中,是商家和用户沟通的桥梁,起着非常重要的作用。


痛点

我们通常来讲把出现在消息会话页面内的内容称做消息卡片,目前消息业务常见的消息卡片有文字、富文本、语音、照片、视频、通知消息,除此之外还有订单详情、推荐商品、核对订单等共计 30 余种消息卡片。目前我们消息卡片都是采用原生来开发,随着业务的日益增多,消息卡片的数量也在成倍的增长,业务方经常提出增加卡片的需求,去开发和维护这些卡片工作量比较大,并且依赖业务方的客户端发版,不够灵活。


现状

目前消息业务在 iOS 端和 Android 端均采用二方库的方式开发,供各个有赞的 App 接入,在 iOS 中采用 Cocoapods 进行二方库的依赖,Android 采用 gradle 来进行二方库的依赖;如果业务方需要增加一种消息卡片从开发到上线按照正常的周期是 1 周到 1 周半,发版周期长、开发效率低。


动态化技术指不依赖 APP 发版,就能进行动态的增加或者修改来更新页面的技术。对于消息卡片这种需要快速迭代、实时调整的业务,动态化具有非常重要的意义。主要优势体现在:


  • 提高人效

  • 缩短版本迭代试错周期

  • 解决版本长尾问题

  • 减少包大小等


整个消息的业务场景如下图所示:



消息聊天以及消息模版都是由消息卡片组成


原生消息卡片

先来说说原生消息卡片的实现方案,这里以 iOS 为例。整体架构设计我们采用 TableView 作为整个页面的容器,采用 MVVM 的架构去设计,架构分为以下模块:


  • 消息卡片数据源配置类 Configurator 负责 VC 和数据源处理类的绑定以及消息管理处理

  • 消息卡片接口管理类负责接收/发送消息数据处理,重发的操作、界面接口(增、删、改、查)

  • 数据源操作类 TableAdapter 负责 TabelView 的代理方式、数据源代理方法的实现,以及一些视图刷新等相关操作

  • 消息卡片内容视图工厂类 ContentFactory 会根据消息类型注册对应的 ContentConfig 进行一个缓存

  • 消息卡片配置类 ContentConfig 是根据消息类型从工厂类中获取的,返回当前消息卡片的宽高(size)、消息体 message、当前渲染的消息卡片视图

  • 消息模型 layout ,根据不同的消息类型生成,会保存当前的消息体以及消息卡片的宽高,为了提升性能,缓存在 TableAdapter 数据源操作类中

  • 消息卡片 cell,根据后端下发不同的卡片类型,从消息卡片配置类中获取不同的 contentView 加到 cell 中,进行消息卡片的展示

  • 消息卡片 contentView,负责消息卡片 UI 布局、数据的渲染、绑定


整个架构如下图所示:



消息原生架构图


方案

关于动态化技术栈的选择

上面介绍了 iOS 端消息卡片渲染架构设计,那么为了让消息卡片具有动态化的能力,但是不会打乱现有原生架构的情况下,我们采用了结合 weex 技术栈来做这件事。为什么用 weex 来提供动态化这样的能力?首先该技术栈已经在有赞移动中扮演者重要的角色,我们团队之前已经做了 weex 无线开发平台,我们团队主导建设了 ZanWeex ,它是一整套解决方案,从开发、构建到发布、热修、数据、监控,全生命周期的平台和工具,目前有赞业务很多模块都是以 weex 来实现,也接入了长连接功能,无须重启 App 实现实时下发的功能,对 weex 有兴趣 的,可以查阅 weex 官网。


因此我们的核心思路是利用 weex 来达到消息动态化的目的。


  • 创建 weex 容器,为了避免容器臃肿, 这里我们没有选择 ViewController 来充当 weex 的容器,而是用 View 来充当容器,里面包裹了一个 WXSDKInstance 进行 weex 的渲染。

  • 原生端创建渲染 weex 的 TableViewCell,将 weex 容器视图添加到 cell 的 contentView 中去,利用 TableView 的重用机制进行 cell 的缓存和重用。


动态化能力

技术架构设计

在架构设计上面,我们在以前原生的 MVVM 的基础上,利用 JS 动态库,配合 weex 达到动态化卡片的能力,做到了 App 不发版的情况下,只需发布 weex 就可以动态添加消息卡片,也可以修改消息卡片的 UI 样式。鉴于这样的设计目标,在这个框架里,主要考虑以下方面:


  • 在不改变原有原生架构的基础上去做消息卡片动态化

  • 页面布局动态化,意思是页面的排版布局,可以通过 weex 端和 JS 端发布来达到动态更新

  • 组件的复用,为了在多种类型的卡片中保持良好的性能,需要对 weex 端容器进行缓存和复用

  • 开发、构建、发布整个流程需要拥有一个完善的平台


JS 动态库

JS 动态库是我们团队出的一个动态化方案的框架,主要功能是提供动态下发的能力;快速修复线上问题;两端特殊复杂的逻辑保持一致等。JS 动态库也是利用 ZanWeex 平台来开发、构建到发布,一整套流程都是完善的,这里我们不去过多的讨论 JS 动态库的相关内容,我们仅仅是用到动态下发的能力,核心思路是:


  • 利用 JS 动态库根据消息类型下发对应的 weex 卡片的 url

  • 利用 JS 动态库根据消息内容和消息类型来计算原生承载 weex 容器的 TableView 的 cell 宽高

  • 利用 JS 动态库下发需要加载 weex 卡片的消息类型

  • 利用 JS 动态库根据消息类型来判断当前的 cell 是否是 weex 卡片 cell


接入 JS 动态库

  • 我们在 JS 动态库中,暴露出获取 weex 卡片对应的 url 方法,入参是消息类型

  • 获取 weex 卡片所在的 cell 的宽高,入参是消息卡片内容和消息类型,JS 将卡片内容解析出来,进行高度、宽度的计算返回给原生。

  • 获取需要支持 weex 卡片的消息类型,原生根据这些类型进行容器 cell 的注册


性能

性能较好,在多个 weex 卡片消息交替出现的时候,为了避免达到性能瓶颈,因此首先考虑到利用原生 TableView / RecyclerView 的重用机制,拿 iOS 来举例,用 weex 的 url 和 TableView 的 identifier 做一个绑定,这样不必自己去维护 weex 卡片的重用和回收。第一版做出来的时候发现,这样在持续加载 weex 卡片的时候 WXSDKInstance 会不停的渲染调用 renderWithURL 方法,这样无疑是消耗比较大的性能去创建 weex 视图。因此我们在 weex 容器中做一个标记,记录上次该容器加载的 url,每次在加载 weex 卡片 cell 的时候去判断当前的 url 是否是上次记录的 url,如果是,就说明这个类型的 weex 卡片之前已经渲染过,WXSDKInstance 实例可以拿到原生传过来的数据进行 refreshInstance;否的话用 WXSDKInstance 进行 renderWithURL,这样可以节省一次 render 重新渲染,从而解决卡片太多,上下滑动的时候会出现短暂的空白现象。


整体流程

  • 消息通道连接的时候,weex 模块去拉取对应的注册的 weex 页面;初始化 JS 动态库,其实也就是拉取 JS 相关的逻辑配置

  • 后端下发消息数据,经过数据解析器将消息经过转化生成 layoutModel 缓存起来

  • 在消息卡片视图工厂类 contentFactory 中,将消息类型传到 JS 端来判断当前消息类型是否需要注册成 weex 卡片

  • 在获取卡片宽高、消息模型的卡片内容配置类 contentConfig 中,将消息类型、消息内容传到 JS 端,返回 weex 卡片宽高

  • 数据操作类去持有 LayoutModel 和 contentConfig 类,在 TableView 代理方法回调的时候,去加载对应的 weex 卡片和宽高,并且将 weex 卡片的 url 作为 identifier 重用标记

  • TableView 加载 weex 容器的 Cell 时传递消息类型到 JS 动态库,然后返回对应的 weex 卡片 url,然后根据 url 将消息卡片内容传递到 weex 容器端去进行渲染或者刷新


架构设计如下图所示:



消息动态化架构图


优化

目前整个流程已经上线,情况比较稳定,极大的提高了开发效率,增加/修改消息卡片做到完全动态化,但是目前我们的方案也有很多不足之处,比如我们期望更好的性能和更高的运行效率、更加动态化的事件处理能力、更加方便的开发体验,对此我们也做了更进一步的规划建设:


  • 组件创建、布局计算、数据绑定机制、从 JS 端获取数据做缓存的优化,提升性能

  • 规范事件点击回调处理,提供跳转商品详情、订单详情、原生特定页面 router 以及 webView 的事件处理

  • 拆分出动态化框架 SDK ,让其他需要用到的业务可以接入,比如一些活动页面


总结

以上是我们整个消息卡片动态化的整体方案,总结来讲就是在原生架构基础上配合 weex 技术栈、JS 动态下发,达到整个动态化的目的,可以算作一个轻量化的动态化方案,算是在动态化方面做一些尝试,也希望可以和广大开发同学一起交流。


参考链接:



本文转载自公众号有赞 coder(ID:youzan_coder)。


原文链接


https://mp.weixin.qq.com/s?__biz=MzAxOTY5MDMxNA==&mid=2455761163&idx=1&sn=32e318bdf0c847021abc5e621193172c&chksm=8c68772ebb1ffe38768f187645f73848879ed6bd7baf8f50a4b6e81556dc8b7ab56868d22579&scene=27#wechat_redirect


2020 年 8 月 08 日 14:052028

评论

发布
暂无评论
发现更多内容

工作三年,小胖连 HashMap 源码都没读过?真的菜!

JavaFish

扩容 hashmap 源码剖析 HashMap底层原理 加载因子

阿里巴巴研究员吴翰清采访提纲:天才少年之路

Nydia

签约计划

Spring Cloud Gateway 和Webflux 请求参数非法字符处理

a1vin-tian

Java Spring Cloud SpringcloudGateway

面试4轮字节Java研发岗,最终拿下2-1Offer(原题复盘)

Java架构追梦

Java 字节跳动 面试

MySQL内置函数

Sakura

4月日更

快来,告诉你一个赚钱的秘诀:金钱的秘密

leoay

赚钱 秘密 金钱的秘密

浅谈BSS3.0产品“守成”之策中 • 业务提升篇

鲸品堂

系统架构 性能调优

ORC格式和PARQUET格式介绍

五分钟学大数据

hive 存储 4月日更

源中瑞区块链农产品溯源--推动农业科技发展

13530558032

区块链电子合同签约,推动合同签约数字化转型

13530558032

python内置数据结构list、set、dict、tuple(二)

若尘

List 数据结构 set 元组 Python编程

万字长文,38 图爆肝 Redis 基础!

JavaFish

redis 数据结构 集合 哈希表 跳表

华为云薛浩:走进视频“新时代”

华为云开发者社区

云原生 视频 华为云 vr 图形处理

FILPool云算力挖矿系统开发源码案例

系统开发咨询1357O98O718

Redis的AOF方案(Redis持久化)

大数据技术指南

redis 4月日更

美国工程院士、谷歌首席架构师 杰夫·迪恩(JeffDean) John 易筋 ARTS 打卡 Week 45

John(易筋)

ARTS 打卡计划

IPFS挖矿系统开发详情案例丨IPFS挖矿矿机源码平台

系统开发咨询1357O98O718

android面试题及答案,我的阿里春招之路分享,附面试答案

欢喜学安卓

android 程序员 面试 移动开发

2021金三银四最全大厂面试题复盘总结,刷完五月进大厂拿35K没问题(Java岗)

Crud的程序员

Java 程序员 架构

智慧平安社区建设--赋能基层治理

13530558032

《采访提纲:声网 Agora.io 资深 iOS 开发工程师--龚宇华》

空城机

活动专区 签约计划 4月日更

四两拨千斤——你不知道的VScode编码TypeScript的技巧

Geek_Willie

专访彩食鲜 CTO 乔新亮:CTO的“升级”秘笈

IT蜗壳-Tango

LiteOS内核源码分析:消息队列Queue

华为云开发者社区

队列 LiteOS LiteOS内核 消息队列Queue 队列池

AUC/ROC:面试中80%都会问的知识点

华为云开发者社区

机器学习 面试 mindspore roc AUC

加密原理详解:对称式加密VS非对称式加密

vivo互联网技术

加密 rsa

重读《重构2》- 以查询取代临时变量

顿晓

重构 4月日更

库存溯源之批次管理

陈俊

溯源 供应链 仓储 冷链 wms

fil云算力挖矿系统开发成功案例丨fil云算力挖矿源码设计

系统开发咨询1357O98O718

apk优化,996页阿里Android面试真题解析火爆全网,附面试答案

欢喜学安卓

android 程序员 面试 移动开发

Spark内存管理与调优

小舰

4月日更

ShadowRealm 与微前端沙箱

ShadowRealm 与微前端沙箱

有赞移动消息卡片动态化方案实践-InfoQ