基于 Web 与混合应用框架的架构,设计一个实时聊天工具,并不是一件轻松的工作:
不论怎样,让我们来看看这个应用是怎么设计的吧。
我们所在的团队,是一个框架(混合应用框架、平台化框架、Web 前端框架)的开发团队。业务方需要基于一个聊天的 SDK,开发一个聊天应用。而这个聊天应用,不仅仅是一个业务方所需要的。其它的业务方,都有可能针对于这个聊天应用有定制需求。
作为一个框架的底层提供方,我们预期我们开发的聊天应用:
在这个聊天应用的设计过程中,我既承当了部分的业务分析职责,又作为一个 “架构师” 设计整个系统的架构。当然了,我主要做的部分是前端 UI 部分的设计,及对应的与原生部分的接口设计、参数传递等。与此同时,在早期的 POC 阶段(概念验证),为了验证理论的可能性,我还作为一个 Android 开发,测试了一系列的接口。
对应的系统架构设计
针对于第二点做一个补充说明。事实上,这已经是我开发的第二个 IM 应用了。在上一个 IM 应用中,我犯了一个不大不小的错误,将 IM 代码和业务代码混合在一起。导致了,这个 IM 部分的功能,无法在后期直接抽离出来。我写第一个版本的 IM 应用时,由于当时的技术限制(只有 Android 开发能力)、背景限制(只开发应用),而没有考虑到二次复用的问题。不过,由于使用的是 Angular.js,也不得不再次用 Angular 实现一个版本。
对应的,写一个简单的电梯演进:
关键因素 | 描述 |
---|---|
对于 | 想集成聊天应用的团队 |
我们的 | 跨平台聊天应用 |
是一个 | 可定制的混合聊天应用方案 |
它可以 | 方便地集成与修改 |
但他不同于 | 基于 Web 的聊天应用 |
它的优势是 | 实时的聊天感受、流畅地用户体验 |
TBC
从业务上来看,可以分为这么几部分:
发送文本消息。文本消息的发送,实际上是最简单的功能。只需要调用一个原生部分的接口,我们也可以实现相应的功能。过程中,唯一比较复杂的地方是,对于消息框的高度的处理。这里的文本框,有最大高度和最小高度的限制,即最小是一行,最长是 3 ~ 4 行。当输入的内容是一行的时候,显示的是一行的高度,二行的时候显示的是二行的高度,三行、四行及以上的时候,显示的是三行的可见区域。
文本消息展示。文本消息的接收属于其中最简单的一部分,并不涉及过于复杂的处理逻辑。
发送语音消息。语音消息是几种消息中最复杂的部分,它涉及到长按输入按钮、变换输入按钮、计时、语音动画、上滑取消、下滑继续、松开发送等一系列的业务。在这几个部分中,最复杂的地方便在于长按和滑动相关的计算。
语音消息播放。由于 SDK 本身的限制,所以播放语音的时候,需要交给原生来处理。于是,前端只需要播放相应的动画即可。然而,过程中有一个比较大的坑是,消息会有一个下载的过程。
发送图片消息。关于图片有一些基本的业务需求:
图片消息播放。由于 iOS 平台对于文件的访问限制,因此提供给前端的是 Base64 编码后的缩略图,点击后又需要显示原来的大图。过程中,即需要获取缩略图的接口,又需要展示大图的接口。
从 UI 来看,我们可以推算出基本的前端数据模型:
从技术上来看,前端比较麻烦的地方在于各个组件的研究。而这时呢,我们使用使用的前端框架是 Angular:
infiniteScrollDistance
需要动态计算。ngx-virtual-scroller
,导是没有遇到什么大坑。longpress
的 directive,添加了对 touchmove
事件的支持。ngx-autosize
,不过稍微修改了一下。然后,比较坑的地方就是适配 Android 和 iOS 机型上的问题了。
为了保持有消息的状态,即创建、发送、取消,需要保持有原有的回调函数。在 Cordova 中,需要通过 keepCallback 来保持这个回调,以多次调用相就的返回值。
同时,值得注意的是,通过 promise 的方式,是不能在一个函数中多次返回结果,因此需要通过 callback 的方式从 JavaScript 获取结果。而在 Angular 框架中,又有外部 callback 需要手动 DetechChange 的问题。
普通的 SDK 封装。
麻烦的地方在于需要多提供一些这么事件:
针对于 iOS 的键盘高度问题,主要是调用第三方输入法(如搜狗)返回的 scrollTop 不对的问题,便需要在原生中处理这个高度。
iOS 的键盘问题
输入框使用的是 position:fixed
,但是在 iOS 上会有遮挡的问题。网上有太多的解决方案了,最后我们采用的是:
setTimeout(function(){
document.body.scrollTop = document.body.scrollHeight;
},300);
iOS 的 WebView 滚动问题
iOS 上需要 -webkit-overflow-scrolling: true
来解决 滚动与回弹效果的问题。这个属性用于控制元素在移动设备上是否使用滚动回弹效果.
iOS 的键盘收起影响元素问题
这是另外一个坑,在键盘收到的时候,底部的某个按钮莫名其妙的消失了。只能再加一个 setTimeout 100 来显示出来。
围观我的Github Idea墙, 也许,你会遇到心仪的项目