通过路由模块来打通应用内外通信、解耦模块间通信

前言

开发客户端路由,一是为了管理客户端内部的模块通信,二是为客户端外部提供与客户端通信的渠道。

内部通信的使用目的是解耦模块之间的依赖,避免引入模块导致的多余维护工作,也可以解决在可能出现循环依赖的模块之间通信问题。同时,引入路由方案,能更好的维护与管理模块的API。

外部通信的使用目的是为产品打造通用的客户端通信协议,比如从推送跳转到用户聊天界面,从浏览器的网页唤起客户端,打开指定内容页面,为小程序的H5端提供Native能力。外部协议更可以统一整个平台客户端的通信API,统一不同平台客户端(如Win、Mac、Android、iOS)的能力。

架构设计

反射跳转管理模块(Performer)

借鉴CTMediator的实现思路,利用OC的Runtime机制,调用函数动态生成来解决模块依赖的问题。

通过TargetClassName(String)、SeletorName(String)、Params(Map)、UserInfo(Map)、Callback(Block)来发起一次函数调用,异步调用通过Callback实现。

在调用前,需要先对函数的各个参数进行基本校验。校验都通过后,使用NSInvocation来组装函数的调用。

需要注意的是,接收NSInvocation的返回值时,返回值的引用计数是需要手动管理的。

路由规则模型(RuleModel)

参考传统的URL规则,抽象出路由的基本信息。

基本结构:scheme://host/path?arg1=aa&arg2=bb

比如:pluto://charon/im/session?id=123&name=ginhoor

分解后 scheme:pluto,host:charon,path:/im/session,params:{id:123,name:ginhoor}

为了方便客户端使用,增加特定参数(不同的平台会使用不同的字段):

  1. vcClassName,iOS的视图控制器类名。
  2. paramsClassName,视图控制器参数接收器的类名。
  3. openType,视图打开方式(模态打开或者导航器打开,是否带有动画)。
  4. isPrivate,指定该规则是否对外使用,如果为False,则只有客户端内部发起才能成功。

为了增强规则的可读性,还增加了几个参数:

  1. demo,填写用于演示的URL字符串。
  2. remark,填写用于描述该规则功能的字符串。

如下,最终将这些规则整理程JSON文件,统一管理维护。

{
    "version":"1.0.0",
    "rules":[
        {
            "iOSVCClassName":"MCGlobalCategorySearchVC",
            "iOSParamsClassName":"MCGlobalCategorySearchVCInputParams",
            "params":{
                "type":1,
                "keywords":"kw",
                "fromVC":"IMSessionVC"
            },
            "host":"route",
            "path":"/home/category_search",
            "demo":"daqun://route/home/category_search?type=1&keywords=kw&fromVC=IMSessionVC",
            "isPrivate":0,
            "remark":"MCGlobalCategorySearchVC"
        }
    ]
}

路由规则配置(Rule Configuration)

维护与管理客户端整个路由规则的配置。

  1. 客户端路由、HTTP Host白名单
  2. 公域Scheme、私域Scheme白名单
  3. 用于客户端生成路由URL的公域Scheme域与客户端路由Host。

客户端启动时,会将本地预埋的JSON路由规则加载到客户端中。同时,需要为服务端提供配置下发方案,当服务端推送新的路由规则时,需要对本地路由规则进行更新。

最后需要为路由规则创建不同字段的索引,优化路由的解析耗时。

URL跳转管理模块 (Open URL)

URL分为三种,一种由客户端生成的本地URL,一种客户端以外途径生成的远程URL了,这两种可以通过路由规则中的isPrivate可以对URL的入口进行权限控制。最后一种是比较特别的HTTP URL,是纯HTTP的请求链接,但除去Scheme与Host,是可以与配置中的路由规则对应的,这也是一种有效的URL。

如果使用客户端路由URL生成二维码,用户当微信扫了这个二维码,而手机上没有安装我们的客户端,那么这次URL唤醒动作将失败,但如果使用中转页面的URL,微信扫了二维码,中转页面会判断是否可以直接唤起我们的客户端,如果不行,则可以引导用户进行下载。

所以HTTP URL这种形式,是为了在生成业务分享二维码时,可以使用中转页面的URL,同时中转页的URL维护规则又与客户端路由规则相兼容,做到最大程度的复用。

在客户端内部的模块间通信时,可以用反射模块直接通信(比如,注销IM用户,跳转会话界面)。也可以根据路由规则,先组装成URL字符串,经业务模块传递后,再后路由模块解析跳转(比如通过卡片消息转发H5分享路由地址)。

最后,如果URL无法通过合法性校验时,路由模块会调用系统的OpenURL来接管后续操作。