58 Android 端 IM 框架及业务拆分设计实践

栏目: Android · 发布时间: 5年前

内容简介:目前IM即时通信对于个大应用来说都是重要的功能部分,而且功能地位较高,线上沟通,58也是对IM系统相当重视,承载各个业务线用户的线上沟通,包括B2C和C2C场景,为了给用户更好的IM体验,我们在IM做了很深入的研发,包括公司内部的IM体系自研底层SDK和server服务,功能优化和版本迭代,我作为一名58APP客户端IM的研发和项目负责人,将我们的IM模块现阶段框架和近期为迎合业务线个性化需求开发而做的业务线拆分工作、项目经验和遇到的问题及解决方案跟大家分享一下,希望能给大家一些帮助。现阶段我们使用的框架

前言

目前IM即时通信对于个大应用来说都是重要的功能部分,而且功能地位较高,线上沟通,58也是对IM系统相当重视,承载各个业务线用户的线上沟通,包括B2C和C2C场景,为了给用户更好的IM体验,我们在IM做了很深入的研发,包括公司内部的IM体系自研底层SDK和server服务,功能优化和版本迭代,我作为一名58APP客户端IM的研发和项目负责人,将我们的IM模块现阶段框架和近期为迎合业务线个性化需求开发而做的业务线拆分工作、项目经验和遇到的问题及解决方案跟大家分享一下,希望能给大家一些帮助。

现阶段IM框架

现阶段我们使用的框架是1年前重构设计的,讲现阶段框架的优缺点,该框架已经历了1年多的版本迭代和需求开发,目前还是比较健壮的。

分层架构

58 Android 端 IM 框架及业务拆分设计实践

IM在我们项目Project中是基础lib库,整体采用分层架构,采用经典三层架构,分层架构结合使用总结以下优缺点:

优点
1.高内聚、低耦合;
2.结构简单,容易理解和开发;
3.开发人员可以只关注整个结构中的其中某一层;
4.可以很容易的用新的实现来替换原有层次的实现;
5.每一层都可以独立测试,其他层的接口通过模拟解决;
6.可以降低层与层之间的依赖;
7.在后期维护的时候,极大地降低了维护成本和维护时间
8.有利于各层逻辑的复用;
缺点
1.代码量增加,开发周期延长;

结合框架的使用,在以下的分析讲解中会逐条在项目中的情况中说明;

表现层

  • IM相关界面的逻辑,展示IM相关数据和界面操作;

  • 功能模块化,UI界面区分出消息列表、会话列表、用户连接状态、消息未读数、帖子信息展示等功能;

业务逻辑层

  • 具体的操作逻辑,对表现层提供接口调用,链接数据访问层,承上启下;

  • 用户输入的数据通过业务逻辑层的处理发给中间层;数据层返回的数据通过业务逻辑层发送给界面展示;

  • 单一职责、易于维护的业务逻辑接口;

  • 该层为核心逻辑层,设计成两部分:

    1)主要逻辑管理类组和API接口,按IM主要功能设计管理类,处理表现层需要的逻辑处理;

    2)转换功能,主要职能是数据转换、加密、数据缓存等,数据转换的设计是为让表现层隔离IM SDK的数据类,将IM SDK有自己的消息bean类转换为我们自己的bean类,已到达上层与SDK的隔离,这样升级SDK或替换SDK,对上层无影响;

数据访问层

  • 数据来源层,使用我司自研的极致IM SDK,Walle库为我们Android平台组自研跨组件通信路由框架,组件化节藕神器;

细解业务逻辑的管理类组和API接口

业务逻辑,是我们的核心逻辑,需要重点设计开发,将设计的重点放在高可用、易维护、可扩展、操作明确简单上,履行好承上启下的责任。

58 Android 端 IM 框架及业务拆分设计实践

如上图所示,将IM的业务按主要功能拆分,功能明确,职责单一,根据类名和注释,可以快速定位功能逻辑,对上层介入使用简单明了,调用下层逻辑更明确,有利于单元测试,具体设计细节:

  1. 接口统一:统一接口类IMClient,包含业务逻辑的管理类成员变量,与上层交互统一使用此 类交互,调用方使用简单,可读性操作性高;

  2. 使代码导航更容易:以IMClient.get...()的方式实现,可发者在使用导航开发更容找到相应方法,一个点就知道后续调用了,例如获取用户信息,IMClient.getIMUserHandle().getUserInfo(),调用方在很短的时间就可以熟悉接口方法,缩短API的学习时间也是我们封装业务逻辑要考虑的;

  3. 职责单一明确:熟悉总结IM的业务逻辑,提炼成高可用的功能接口,先将场景罗列,再抽象,明确管理类的职责,使管理类易维护可扩展,有利于单元测试;

  4. 静态代码块初始化:将初始化操作放在IMClient的静态代码块中执行,当类在首次使用时才可初始化IM逻辑,较初始化操作放在Application的onCreat中有3个优点:

    1)可以不影响APP的启动式长,因为初始化操作放在Application的onCreat中是会耗时影响启动时长的,这样做就避免了这个影响;

    2)可以避免将IM的类打在主dex中,一般在Application的onCreat中执行初始化的相关依赖类会被keep到MainDexList中,如果太大了,也会报方法数超的错误,所以应该尽尽量减少他的大小;

    3)对上层是闭合的,有效隔离上层逻辑,上层无法修改和不用关心IM的初始化。

以上是对我们现使用的框架总结,讲的较为简单,好多细节还未讲到,进入我们另一个重要内容IM业务线拆分的讲解。

IM业务线拆分

拆分背景

58APP是多业务线并行开发的,然而IM的native聊天一直是多业务线共用一套逻辑,共用一个聊天界面,显示判断不同的业务线,显示不同的场景需求,代码统一由我们无线侧开发测试,随着业务的发展,共用逻辑就渐渐暴露出了许多问题:

  • 无法满足业务线强个性化的需求;

  • 由于统一由无线侧开发,开发测试资源有限,无法快速完成业务线的需求,造成需求等待的情况;

为了解决这些问题,我们决定将IM做拆分,支持业务线自行开发,做个性化需求,无线侧提供基础服务框架

IM拆分目标

开始实施前先确定目标

  • 开发聊天界面基础框架服务

  • 面向业务线需求开发接口

  • 接口简要、易懂

  • 使用组合模式组件化思想让界面操作更灵活

  • 单一职责设计

  • 易扩展,易维护

IM拆分转换器

之前所有的聊天场景都是使用的唯一的聊天详情页,为满足业务线的独立开发,必须要将聊天详情页由业务线自行控制开发,这就需要多个聊天详情页,每个业务线可自行开发自己的聊天界面,也就是业务线想启动聊天界面时启动本业务线的聊天界面即可,任何场景启动聊天界面都是通过协议在跳转中心控制启动相应界面的,那如何控制启动指定的聊天界面呢?达到房产启动房产聊天界面、招聘启动招聘的聊天界面呢?为了实现这个目的我们设计了转换器,具体看下面的设计:

58 Android 端 IM 框架及业务拆分设计实践

  1. 设计任何场景启动IM聊天界面时都通过跳转中心,使用跳转协议;

  2. 跳转协议由跳转中心控制解析,解析出具体的业务参数;

  3. 设计配置表,配置关系是业务参数(key)对应具体聊天界面协议(value);

  4. 配置表本地缓存默认的,由server端下发更新,动态可控,灵活配置,同时还可以快速实现上线时灰度控制风险,如果有问题可以及时降级到原聊天界面;

  5. 通过业务参数找出对应的聊天界面协议,启动相应的聊天界面,就可以实现房产业务启动房产业务线聊天界面的。

    该设计方案的优点:
    a.入口统一:所有的聊天界面都适用跳转协议通过跳转中心控制,统一维护管理;
    b.server端控制配置表:将配置表由server 端控制,动态更新,可控性高;
    c.业务线可控制跳转协议:指定具体跳转到哪个聊天界面,也可扩展添加聊天界面;
    d.可控制灰度降级:任何大需求在开发时都需要考虑到灰度可控,避免带来灾难,正因为前面讲到的配置表由server端控制,所以一旦发现问题,完全可以由server端更新配置表,将启动聊天界面的协议降级到跳转原聊天界面,有效控制线上风险。

上面讲解是启动聊天界面的逻辑转换器,这是前提,下面开始讲解我们的聊天界面,它又该如何设计如何实现呢?那就一起来看一下吧。

IM聊天界面的设计

通过转换器那个设计大家已经看到了,业务线的聊天界面都是继承自聊天基类,由于业务线是新开发,为快速让业务线RD能实现需求开发,我们需要提供基础服务框架,同时还要兼顾其他聊天场景的开发,那这个聊天基类就是我们要提供的基础服务了,业务线基于聊天基类开发,要想枝叶繁茂,必须要根基好,那就讲一下我们的基类。

IM聊天界面基类模型设计

构建界面模型,直接上图:

58 Android 端 IM 框架及业务拆分设计实践

  1. 基类IMChatBasePage:基类继承自Activity定义为抽象类,符合开闭原则,有利于以后扩展,可控制子类逻辑方法实现和复用,含有界面上下文对象,由组件组合而成,同时实现想要对子类暴露的API接口(作用下面详细讲解);

  2. 基类界面上下文:定义为前界面的信息、环境资源,包含以下部分

  • IMMsgOperator:负责消息相关操作,发送漫游消息,插入本地消息,临时展示消息,为什么把这个类放在上下文中呢,因为界面操作一个主要的功能是收发消息;

  • IMSession:当前界面的信息类,包含聊天对象的信息,聊天场景的业务数据信息;

  • Context:Activity的context,用于资源文件的操作处理,和信息获取;

  • 组件通信路由IMRouter:用于组件间通信使用,可以使组件解藕相互数据传递交互,区别与EventBus的是,该路由设计为界面相关,也就是组件间的数据传递作用域为当间界面,这样可以避免多个界面共存时数据的共享混乱;

  • 组件组合:整个界面的功能按照组合模式组件化的思想设计,基类由组件组成,下面会详细讲解该思想;

  • 对业务线API接口:这是使用的面向接口开发,将对业务线子类提供的功能API都使用接口的方式实现,可读性和可扩展性高;

  • 这样我们的基类基本上就设计完成,业务线开发继承基类IMChatBasePage,可以快速实现聊天的基本功能,同时又可以灵活扩展自己的功能,任意添加、删除、组合组件,满足个性化需求开发。

    IM聊天界面基类的组合模式组件化思想

    业务线的小伙伴要基于我们的基类做开发,开发个性化需求,所以基类界面逻辑要灵活可控,为实现这点我们可以借鉴一些优秀的思想,比如我们的Android系统API,Fragment当时的出现就是为了解决Activity的模块片段化,使Activity可以任意组装拆卸,add、replace、remove...动态控制Activity界面的显示,灵活性大大提高,View和ViewGroup的组合模式,表示部分与整体的层次,介于该思想结合当下较类似的组件化概念,动态可控,我们将聊天界面的设计思想确立为组合模式组件化思想。

    58 Android 端 IM 框架及业务拆分设计实践

    1. 组件化:把整个聊天界面按照功能组件化,对功能逻辑可以动态添加删除,每个组件都是完整的功能体,职责明确,代码解藕,可以单独运行,组件之间可以数据传递,目前基类抽象出的组件有以下部分:

      58 Android 端 IM 框架及业务拆分设计实践

    2. 组合模式:Android中重要的界面UI类View和ViewGroup就是采用组合模式,我们正式借鉴它的使用,创建两个重要的类IMUIComponent和IMUIComponentGroup,IMUIComponentGroup包涵多个IMUIComponent,IMUIComponentGroup继承自IMUIComponent,可以使我们的界面功能结构整体层次清晰,模块调用简单,节点自由增加、删除、替换;

    3. 组件赋能:

    • 基类界面上下文IMChatContext,如上文讲解的IMChatContext的作用,提供当前界面的信息和环境资源;

    • 组件绑定的View,处理界面UI逻辑;

    • 组件的生命周期,主要绑定的是Activity的生命周期回调,实现生命周期方法,处理适当时机的逻辑;

    • 组件路由方法回调,调用路由传递组件间的数据和交互,实现组件间的解藕。

  • 每个组件可用MVC、MVP、MVVM等设计模式,正如我们借鉴的Fragment,每个Fragment都可以在使用处理UI、逻辑和数据的设计模式,以便提高我们组件的易维护性;

  • 组合模式组件化思想我认为可作为界面通用设计思想,将界面拆分开,可以同时分工多个人开发,对于版本需求迭代开发维护都比较友好,尤其是界面逻辑较复杂的场景。

    自定义消息类型的优化实现

    聊天界面消息列表由多个消息类型组成,通常包括文本、语音、图片、地理位置、卡片消息等多种,通用消息类型由基类实现,那如果业务线开发想要自定义一种消息类型如何实现呢?定义一种消息类会在多个场景使用,如消息中心(会话列表)、通知栏、聊天界面列表,如何一次定义多个场景能适配显示呢?

    代理模式使消息类型的添加工作简化

    带着问题讲解,首先是聊天界面列表,聊天界面列表使用ListView和ListAdapter实现,ListAdapter一般写法是列表信息多个Item组成,每个Item类型由ViewHolder和消息Bean组成,构建一个ViewType类型需要在ListAdapter的getItemType的方法中添加映射关系、在getViewTypeCount()方法中+1,操作相当繁琐,为了简化操作,我们使用了代理模式,保留原有ViewHolder的逻辑,创建代理类代理Viewholder,创建带有代理管理能力的Adapter,可以注册代理类,方法getItemType和getViewTypeCount的返回值交给代理管理类处理,达到定义一个Viewholder后,不需要关心Adapter的ItemType操作,简化操作。

    装饰模式让消息类型可在多个场景适配显示

    一个消息类型的组成包括Viewholder、消息Bean,而这两个类需要处理好多业务逻辑,如是否为当前版本可支持,消息中心列表提示文案,View的展示,消息协议转换为消息Bean等操作,这一系列的操作让新开发者摸不着头脑,为解决这个问题我们使用装饰模式,创建装饰类,引用ViewHolder和消息Bean对象,抽象出这两个类的功能实现,让装饰者完成他们的调用,将需要实现的职责功能明确,将分散逻辑聚合在装饰者中,让开发者自定义消息功能思路更清晰。

    工厂模式注册让消息类型随意添加

    一个装饰者代表一个消息类型,使用工厂模式统一管理、注册。

    总结

    技术服务于业务需求,IM的框架优化和拆分都是为了我们APP中的业务开发,让IM技术满足现在和今后的业务需求,我们一直在努力优化,业务线介入开发可考验我们现有技术框架是否能满足IM个性化需求,对遇到的问题和解决方案我会不断总结实践创新,希望能多一些分享交流。

    58 Android 端 IM 框架及业务拆分设计实践


    以上所述就是小编给大家介绍的《58 Android 端 IM 框架及业务拆分设计实践》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

    查看所有标签

    猜你喜欢:

    本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

    Database Design and Implementation

    Database Design and Implementation

    Edward Sciore / Wiley / 2008-10-24 / 1261.00 元

    * Covering the traditional database system concepts from a systems perspective, this book addresses the functionality that database systems provide as well as what algorithms and design decisions will......一起来看看 《Database Design and Implementation》 这本书的介绍吧!

    JS 压缩/解压工具
    JS 压缩/解压工具

    在线压缩/解压 JS 代码

    RGB HSV 转换
    RGB HSV 转换

    RGB HSV 互转工具