Android IM即时通讯框架

·  阅读 976

因为我写文章水平不好,解释的也不好,建议下载代码一起食用

GitHub

里面可能写了一些其他我在尝试的东西,但是不影响根据文章了解框架

Github传送门

整体框架图

消息Bean的关系图

消息Bean类看起来好像比较多层级,但是我感觉这样分比较清晰,而且也可以无限扩展 image.png

消息派发流程图

一个非常简单的流程和设计,但是消息派发的过程十分清晰 image.png

进入代码

IMManger 消息的入口 这里可以看到,添加了IM的消息监听后,直接把消息传递给了 IMDispatcher,让他去做消息的处理(这里取名字取得不是很好) image.png

IMDispatcher 消息的处理器 首先看到IMDispatcher定义的一些变量

有解析器的List,拦截器对象,分发器工厂List image.png

而解析消息就会用到上面几个变量,而整个调用过程是这样的

  • 首先会遍历解析器集合,只要添加到解析器List中,他就会去遍历他,直到解析出该消息为止。这里为什么要用集合呢,因为你的解析器可能会有多种,假设你System消息分成了5组大的类型,他们的解析方法可能有一些差异,这时,你只需要写5个解析器并且添加到List就行了,省去了只有一个解析器时,做各种if判断操作

  • 接着到拦截器,拦截器就是一个实例对象,我想着拦截消息应该不会有太多,所以直接弄成实例好了

  • 最后是分发器,只要添加到分发器工厂List,实现接口方法,就能获得你想要的消息,对于使用者来说,根本不需要关心你之前的操作,我只要实现接口就行了

image.png

实际应用

以传递一个自定义消息来举例

1.看一下自定义消息的基类

abstract class BaseCustomMsg<T> : BaseMsgBean() {
    // 当你发送一条消息时,会传入一个你的Bean,会转换成String保存在这
    private var param = ""

    // 当你获取消息时候,paramBean就是你当前消息的Bean类
    @Expose(serialize = false)
    var paramBean: T? = null
        get() {
            if (field == null) {
                val t = TypeUtils.findNeedType(javaClass)
                // 因为发送时,param已经存着发送方Bean类的String
                // 所以你获取消息时,获取paramBean,这里就会做转化,确保你拿到的是是一个Bean实例
                field = TypeUtils.fromJson<T>(param, t)
            }
            return field
        }
        private set

    /**
     * 这里是创建消息时调用的,所有自定义消息创建发送时,都要调用此方法,目的是
     * 1.将你要传递的Bean转换成String传递
     * 2.将你的消息赋值一个msgAction,作为消息的标识
     */
    open fun createMsg(paramBean :T){
        // 新建一个传递的数据对象
        val dataObj = JSONObject()
        dataObj.put("msgAction", getAction())
        // 转成String
        param = TypeUtils.toJson(paramBean)

        // 放入value保存
        dataObj.put("value", param)

        val timCustomElem = TIMCustomElem()
        timCustomElem.data = dataObj.toString().toByteArray()

        mTxMessage.addElement(timCustomElem)
    }

    /**
     * 这里是获取消息解析时调用的,所有自定义消息解析时,都要调用此方法
     * 为了解析出msgAction和传递过来的值
     */
    override fun addMsgContent(mTxMessage: TIMMessage): BaseMsgBean {
        val element = mTxMessage.getElement(0) as TIMCustomElem
        val dataJson = String(element.data)
        val jsonObject = JSONObject(dataJson)
        msgAction = jsonObject.optString("msgAction")
        param = jsonObject.optString("value")
        return this
    }
}

复制代码

2.接着如果我想定义一个Pk请求消息,并且需要传递一些参数,那么我就可以这样定义了,非常的简单,也不需要什么其他东西,只需要你的bean类和给该消息一个标识msgAction

class PkReqMsg : BaseCustomMsg<PkReqMsg.PkMsgParam>() {

    data class PkMsgParam(
        var playUrl: String = "",
        var isAgain: Boolean = false,
        var pk_id: String = ""
    )

    override fun getAction() = MsgType.CUSTOM_PK_REQ
}
复制代码

3.那么怎么发送该Pk请求消息呢?

  • 可以看到createMsg接受了我们想要携带的参数Bean,而基类的createMsg会将bean类转成String,再赋值给param,接着和msgAction一起打包发送出去,可以回顾一下基类看一下
// 消息请求bean
val pkReqMsg = PkReqMsg()
// 你要携带的参数Bean
val pkMsgParam = PkReqMsg.PkMsgParam("pk消息", false, "12345")
// 调用基类的方法
pkReqMsg.createMsg(pkMsgParam)
// 发送
IMManager.sendMessage(pkReqMsg)
复制代码

4.那么怎么解析消息

  • 解析消息(注意TIMElemType的类型是腾讯自己定义的)
  • 根据MsgAction去找到对应的消息类型,newInstance实例化出来,接着调用基类的方法的decorateMsg,最终最调用到 addMsgContent 去获取内容

image.png

5.怎么获取消息呢?

  • 添加,获取,移除

image.png

6.更加简单的获取方式,这里不做阐述,可以根据代码看一下

只需要填入msgAction对应的消息bean,就可以直接获取消息了,

避免了像上面一个,在一个方法中,做各种判断去转型再拿消息 image.png

结尾

这个框架只是用腾讯IM做个例子,其他即时通讯应该可以套用一下,如果你有更加好的架构想法,欢迎加好友交流,评论区交流哈,多交流才能发现不足,也能发觉到自己想不到的层面

分类:
Android
标签:
分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改