1、HarmonyChat是什么?
HarmonyChat是一個簡潔的鴻蒙NEXT上的基于WebSocket協(xié)議的聊天客戶端 ,它基于MobileIMSDK通信庫, 有完善的網(wǎng)絡(luò)通信通力、簡潔的聊天界面UI、合理的代碼拆分和邏輯實(shí)現(xiàn),非常適合學(xué)習(xí)研究或直接用于簡單的鴻蒙NEXT單頁聊天項(xiàng)目中 。
HarmonyChat的源碼下載請見本文:“5、源碼的開源倉庫地址”。
2、為什么有HarmonyChat?
我本身是MobileIMSDK開源框架的作者,正好近期趁著開發(fā)MobileIMSDK的鴻蒙NEXT端演示界面的機(jī)會,把相關(guān)的UI代碼整理出來,希望在當(dāng)前鴻蒙有質(zhì)量的資料比較少的情況下,能帶給需要的人一點(diǎn)啟發(fā)或幫助。
你如果在HarmonyChat中看到有關(guān)MobileIMSDK的資料和字眼也不要奇怪,因?yàn)楸竟こ讨械拇a、資料、想法,都是從MobileIMSDK的鴻蒙NEXT端工程中整理和抽取出來的,目的是方便需要的人從單獨(dú)的UI界面和功能來學(xué)習(xí)和使用。
3、誰需要HarmonyChat?
目前高質(zhì)量的鴻蒙NEXT端IM聊天方面的開源代碼還非常少(幾乎找不到有價值的開源分享),所以我希望能把自已編寫的相關(guān)代碼抽取出來供需要的人借鑒和使用,共同進(jìn)步。
HarmonyChat特別適合以下開發(fā)者學(xué)習(xí)、研究或直接使用:
- 1)• 想學(xué)習(xí)使用ArkTS和ArkUI開發(fā)聊天界面的;
- 2)• 想學(xué)習(xí)如果在鴻蒙NEXT中對接網(wǎng)絡(luò)通信代碼的;
- 3)• 想學(xué)習(xí)IM聊天程序如何在鴻蒙NEXT中實(shí)現(xiàn)UI和網(wǎng)絡(luò)數(shù)據(jù)的邏輯分離的;
- 4)• 想得到可以直接使用的單頁聊天界面的;
- 5)• 想要開發(fā)IM聊天應(yīng)用,但需要一個腳手架作為起點(diǎn)的。
4、實(shí)現(xiàn)了哪些特性?
1)• 實(shí)現(xiàn)了一個UI簡潔、代碼清晰、邏輯分層合理的聊天界面(可以直接復(fù)制到一些單頁聊天產(chǎn)中品用,比如客服聊天);
2)• 消息的送達(dá)狀態(tài)在UI界面上會自動更新顯示(包括發(fā)送中、已送達(dá)、送達(dá)失敗);
3)• 網(wǎng)絡(luò)連接狀態(tài)的UI顯示(含心跳呼吸燈效果);
4)• 實(shí)現(xiàn)了真正的網(wǎng)絡(luò)通信和聊天(包括完整的多端互踢、網(wǎng)絡(luò)心跳、掉線重連、消息重傳、消息應(yīng)答、消息去重等),這是基于MobileIMSDK通信庫實(shí)現(xiàn)的;
5)• 實(shí)現(xiàn)了隱私提醒、閃屏、登錄界面的判斷和跳轉(zhuǎn)邏輯(可以直接復(fù)制這幾個界面到你的產(chǎn)品中去用用);
6)• 鴻蒙NEXT的List列表在LazyForEach帶來的性能優(yōu)化情況下的動態(tài)UI刷新;
7)• 利用DataSource和一個全局消息緩存管理機(jī)制實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)與UI的解偶(這是IM消息和UI解偶的關(guān)鍵);
8)• 實(shí)現(xiàn)了跟微信基本一致的消息時間計(jì)算和顯示邏輯(人性化時間、超過2分鐘才顯示時間);
9)• 合理的拆分了不同消息類型組件式擴(kuò)展的實(shí)現(xiàn)邏輯,方便擴(kuò)展更多消息類型的UI顯示;
10)• 解決了消息文本超長導(dǎo)致Row()組件被擠出屏幕可視區(qū)顯示的問題(這可能是鴻蒙的bug);
11)• 一些鴻蒙NEXT簡單動畫的應(yīng)用;
12)• 適配全面屏;
13)• 詳細(xì)的代碼注釋,便于學(xué)習(xí)研究。
5、源碼的開源倉庫地址
HarmonyChat源碼在以下托管倉庫都是同步更新:
開源MobileIMSDK的源碼托管倉庫:
6、HarmonyChat工程概覽
7、實(shí)際運(yùn)行截圖
1)Demo 的登陸界面運(yùn)行截圖(點(diǎn)擊可看大圖 ▼):
2)Demo 的主界面運(yùn)行截圖(點(diǎn)擊可看大圖 ▼):
3)Demo 運(yùn)行的同時,可以查看詳細(xì)的 log 輸出(方便調(diào)試):
8、技術(shù)要點(diǎn)1:關(guān)于服務(wù)端的部署和運(yùn)行
HarmonyChat中默認(rèn)連接的是MobileIMSDK開源工程的測試服務(wù)端,因條件有限,建議你自已部署服務(wù)端。資料請參考:《MobileIMSDK開源服務(wù)端的部署指南》。
你也可以直接拉取MobileIMSDK開源服務(wù)端的源碼自行編譯和運(yùn)行,就像下面這樣:
PS: MobileIMSDK開源服務(wù)端的源碼可以在這個目錄下找到:點(diǎn)此查看 ◄,也可以直接用編譯好的程序雙擊run.bat就可以運(yùn)行(點(diǎn)此查看 ◄)。
如上圖所示: HarmonyChat中因?yàn)橛玫降氖区櫭蒒ext的WebSocket協(xié)議,所以請確保MobileIMSDK開源服務(wù)端的WebSocket端口是開啟的哦。
9、技術(shù)要點(diǎn)2:關(guān)于消息文本超長導(dǎo)致Row()組件被擠出屏幕可視區(qū)的問題
問題描述: 這是我在編寫文本聊天消息組件的過程中遇到的,原圖我沒有截出來,問題大致是下圖這樣(這圖是我在網(wǎng)上找的)。
問題的原因就是: 為了實(shí)現(xiàn)聊天消息氣泡中的超長文本能自適應(yīng)長度和高度,所以是無法使用layoutWeight屬性的,這會導(dǎo)致Text()所在在Row()父組件,無法正確的計(jì)算自已的寬度。
解決辦法: 就是用Flext()替代Row(),如下圖所示。
10、技術(shù)要點(diǎn)3:關(guān)于仿微信消息時間顯示的代碼實(shí)現(xiàn)
大家平時使用微信比較多,它的消息時間顯示是很人性化的,所以現(xiàn)在開發(fā)IM聊天應(yīng)用時,這個消息時間的人性化顯示是必做的。
以下是本工程中實(shí)現(xiàn)的效果(跟微信幾乎一樣):
如上圖所示,主要實(shí)現(xiàn)的是: 對消息時間進(jìn)行了人性化處理(比如昨天上午xx、今天下午xx、星期x等),以有超過2分鐘才顯示時間的這種邏輯。
完整代碼涉及到幾個方法,關(guān)鍵代碼如下 (具體大家可以看 /entry/src/main/ets/pages/utils/ToolKits.ets 中的相關(guān)方法):
/**
* 仿照微信中的消息時間顯示邏輯,將時間戳(單位:毫秒)轉(zhuǎn)換為友好的顯示格式.
*
* 1)7天之內(nèi)的日期顯示邏輯是:今天、昨天(-1d)、前天(-2d)、星期?(只顯示總計(jì)7天之內(nèi)的星期數(shù),即<=-4d);
* 2)7天之外(即>7天)的邏輯:直接顯示完整日期時間。
* @param timestamp 時間戳(單位:毫秒),形如:1550789954260
* @param mustIncludeTime true表示輸出的格式里一定會包含“時間:分鐘”
* ,否則不包含(參考微信,不包含時分的情況,用于首頁“消息”中顯示時)
* @param timeWithSegmentStr 本參數(shù)僅在mustIncludeTime=true時有生效,表示在時間字符串前帶上“上午”、“下午”、“晚上”這樣的描述
*
* @return 輸出格式形如:“剛剛”、“10:30”、“昨天 12:04”、“前天 20:51”、“星期二”、“2019/2/21 12:09”等形式
* @author Jack Jiang([url=http://www.52im.net/thread-2792-1-1.html]http://www.52im.net/thread-2792-1-1.html[/url])
*/
static getTimeStringAutoShort2(timestamp: number, mustIncludeTime: boolean, timeWithSegmentStr: boolean): string {
// 當(dāng)前時間
let currentDate: Date = new Date();
// 目標(biāo)判斷時間
let srcDate: Date = new Date(timestamp);
let currentYear: number = currentDate.getFullYear();
let currentMonth: number = (currentDate.getMonth()+1);
let currentDateD: number = currentDate.getDate();
let srcYear: number = srcDate.getFullYear();
let srcMonth: number = (srcDate.getMonth()+1);
let srcDateD: number = srcDate.getDate();
let ret: string = '';
// 要額外顯示的時間分鐘
let timeExtraStr = '';
if(mustIncludeTime) {
// let timeExtraStr = (mustIncludeTime ? " " + _formatDate(srcDate, "hh:mm") : "");
timeExtraStr = " "+ToolKits.getTimeHH24Human(srcDate, timeWithSegmentStr);
}
// 當(dāng)年
if(currentYear === srcYear) {
let currentTimestamp: number = currentDate.getTime();
let srcTimestamp: number = timestamp;
// 相差時間(單位:毫秒)
let deltaTime: number = (currentTimestamp-srcTimestamp);
// 當(dāng)天(月份和日期一致才是)
if(currentMonth === srcMonth && currentDateD === srcDateD) {
// // 時間相差60秒以內(nèi)
// if(deltaTime < 60 * 1000)
// ret = "剛剛";
// // 否則當(dāng)天其它時間段的,直接顯示“時:分”的形式
// else
// ret = _formatDate(srcDate, "hh:mm");
// 當(dāng)天只需要顯示時間分鐘,且必須顯示“上午”、“下午”這樣的時間段描述
ret = ToolKits.getTimeHH24Human(srcDate, true);
}
// 當(dāng)年 && 當(dāng)天之外的時間(即昨天及以前的時間)
else {
// 昨天(以“現(xiàn)在”的時候?yàn)榛鶞?zhǔn)-1天)
let yesterdayDate:Date = new Date();
yesterdayDate.setDate(yesterdayDate.getDate()-1);
// 前天(以“現(xiàn)在”的時候?yàn)榛鶞?zhǔn)-2天)
let beforeYesterdayDate: Date = new Date();
beforeYesterdayDate.setDate(beforeYesterdayDate.getDate()-2);
// 用目標(biāo)日期的“月”和“天”跟上方計(jì)算出來的“昨天”進(jìn)行比較,是最為準(zhǔn)確的(如果用時間戳差值
// 的形式,是不準(zhǔn)確的,比如:現(xiàn)在時刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00,
// 這兩者間只相差2小時,直接用“deltaTime/(3600 * 1000)” > 24小時來判斷是否昨天,就完全是扯蛋的邏輯了)
if(srcMonth === (yesterdayDate.getMonth()+1) && srcDateD === yesterdayDate.getDate()) {
ret = "昨天"+timeExtraStr;// -1d
}
// “前天”判斷邏輯同上
else if(srcMonth === (beforeYesterdayDate.getMonth()+1) && srcDateD === beforeYesterdayDate.getDate()) {
ret = "前天" + timeExtraStr; // -2d
} else{
// 跟當(dāng)前時間相差的小時數(shù)
let deltaHour: number = (deltaTime/(3600 * 1000));
// 如果小于或等 7*24小時就顯示星期幾
if (deltaHour <= 7*24){
let weekday = new Array<string>(7);
weekday[0]="星期日";
weekday[1]="星期一";
weekday[2]="星期二";
weekday[3]="星期三";
weekday[4]="星期四";
weekday[5]="星期五";
weekday[6]="星期六";
// 取出當(dāng)前是星期幾
let weedayDesc: string = weekday[srcDate.getDay()];
ret = weedayDesc + timeExtraStr;
}
// 否則直接顯示完整日期時間
else
ret = ToolKits.formatDate(srcDate, "M月d日")+timeExtraStr;
}
}
}
// 往年
else{
ret = ToolKits.formatDate(srcDate, "yy年M月d日")+timeExtraStr;
}
return ret;
}
11、技術(shù)要點(diǎn)4:關(guān)于網(wǎng)絡(luò)數(shù)據(jù)與UI界面解偶的實(shí)現(xiàn)
在IM聊天應(yīng)用中,網(wǎng)絡(luò)數(shù)據(jù)與UI界面解偶是非常關(guān)鍵的,否則網(wǎng)絡(luò)代碼的復(fù)雜性跟應(yīng)用層邏輯的復(fù)雜性合并在一起,那代碼會越寫越困難。
HarmonyChat中主要是借助了一個全局的消息數(shù)據(jù)管理器和IDataSource,實(shí)現(xiàn)了與聊天列表UI界面的解偶。
全局的消息數(shù)據(jù)管理器代碼實(shí)現(xiàn) (詳見 /entry/src/main/ets/pages/utils/MessagesProvider.ets):
/**
* 聊天消息的緩存數(shù)據(jù)管理提供者(集中管理所有的聊天消息和指令,消息來源為網(wǎng)絡(luò)層通信數(shù)據(jù)包和本地發(fā)出的包
* ,消息顯示方式通過MessagesDataSource與UI界面進(jìn)行解偶顯示)。
*
* 代碼參考自IM產(chǎn)品RainbowChat:[url=http://www.52im.net/thread-19-1-1.html]http://www.52im.net/thread-19-1-1.html[/url]
*
* @author Jack Jiang([url=http://www.52im.net/thread-2792-1-1.html]http://www.52im.net/thread-2792-1-1.html[/url])
*/
export default class MessagesProvider {
/** 聊天界面中,消息的顯示時間間隔(單位:毫秒):默認(rèn)是2分鐘內(nèi)的消息只在第一條消息上顯示時間,否則會再次顯示時間 */
// 參考資料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url]
private static readonly CHATTING_MESSAGE_SHOW_TIME_INTERVAL: number = 2 * 60 * 1000;
/** 真正的聊天軟件中,此處應(yīng)改造為<key=uid, value=Array<Message> >這樣的Map集合,用于按uid分別存儲與各好友的聊天消息 */
private messages: Array<Message> = [];
/**
* 加入一條新消息。
*
* @param m 消息對象
*/
putMessage(m: Message): void {
// 以下代碼用于判斷并實(shí)現(xiàn)仿微信的只顯示2分鐘內(nèi)聊天消息的時間標(biāo)識(參考資料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url])
let previousMessage: Message | undefined = undefined;
let messagesSize: number = this.messages.length;
if (messagesSize > 0) {
previousMessage = this.messages[messagesSize - 1];
}
MessagesProvider.setMessageShowTopTime(m, previousMessage);
// 將此新消息對象放入數(shù)據(jù)模型(列表)
this.messages.push(m);
// 通知應(yīng)用層更新ui
IMClientManager.getInstance().getEmitter().emit(UIEvent.UIEVENT_messageAdded, this.messages.length - 1);
}
/**
* 獲得消息數(shù)據(jù)緩存集合。
*
* @returns 消息數(shù)據(jù)緩存集合
*/
getMessages(): Array<Message> {
return this.messages;
}
/**
* 添加一條系統(tǒng)消息(顯示在聊天列表中)。
*
* @param content 消息內(nèi)容
*/
addSystemMessage(content: string): void {
let m: Message = Message.createChatMsgEntity_INCOME_SYSTEAMINFO('0', content, 0);
this.putMessage(m);
}
/**
* 更新指定指紋碼的消息的發(fā)送狀態(tài)(更新單條消息)。
*
* @param fingerPrint 消息指紋碼(消息id)
* @param sendStatus 發(fā)送狀態(tài),see {@link MsgSendStatus}
*/
updateMessageSendStatus(fingerPrint: string, sendStatus: MsgSendStatus): void {
// 遍歷消息列表
for(let i = 0; i < this.messages.length; i++) {
let m = this.messages[i ];
// 對符合條件的消息對象進(jìn)行消息發(fā)送狀態(tài)的設(shè)置
if(m && m.isOutgoing() && m.fingerPrintOfProtocal === fingerPrint) {
// 更新狀態(tài)
m.sendStatus = sendStatus;
// 通知應(yīng)用層更新ui(參數(shù)就是消息所在索引)
IMClientManager.getInstance().getEmitter().emit(UIEvent.UIEVENT_messageUpdate, i);
}
}
}
/**
* 更新指定指紋碼的消息的發(fā)送狀態(tài)(更新多條消息)。
* 目前用于QoS送達(dá)機(jī)制中告訴應(yīng)用層有哪些原始消息報文未成功送達(dá)給對方。
*
* @param protocals 原始消息報文對象數(shù)組,數(shù)組中Protocal對象指紋碼(消息id)就是本次要更新的對象,這個數(shù)組目前來自于SDK的 EventType.onMessagesLost 事件通知
* @param sendStatus 發(fā)送狀態(tài),see {@link MsgSendStatus}
*/
updateMessagesSendStatus(protocals: Protocal[], sendStatus: MsgSendStatus): void {
let updateIndexes: number[] = [];
// 遍歷消息列表
// this.messages.forEach((m: Message) => {
for(let mi = 0; mi < this.messages.length; mi++) {
let m = this.messages[mi];
for(let i = 0; i < protocals.length; i++){
let p = protocals[i ];
// 對符合條件的消息對象進(jìn)行消息發(fā)送狀態(tài)的設(shè)置
if(m && m.isOutgoing() && m.fingerPrintOfProtocal === p.fp) {
// 更新狀態(tài)
m.sendStatus = sendStatus;
// 加入已更新索引列表集合
updateIndexes.push(mi);
break;
}
}
}
if(updateIndexes.length > 0) {
// 通知應(yīng)用層更新ui(參數(shù)就是消息所在索引)
IMClientManager.getInstance().getEmitter().emit(UIEvent.UIEVENT_messagesUpdate, updateIndexes);
}
}
/**
* 清空所有消息。
*/
clear(): void {
this.messages = [];
}
/**
* 為當(dāng)前的消息對象,設(shè)置是否顯示消息時間標(biāo)識。
*
* 此時間顯示邏輯是與微信保持一致的:即只顯示5分鐘內(nèi)聊天消息的時間標(biāo)識,參考資料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url]
*
* @param theMessage 當(dāng)前消息對象,不可為null
* @param previousMessage 當(dāng)前消息的自然時間的上一條消息,此消息可為空(此為空即表示當(dāng)前消息就是消息集合中的第一條消息)
*/
private static setMessageShowTopTime(theMessage: Message, previousMessage: Message | undefined): void {
if(theMessage) {
if(previousMessage === undefined) {
theMessage.showTopTime = true;
return;
}
// 以下代碼用于判斷并實(shí)現(xiàn)仿微信的只顯示5分鐘內(nèi)聊天消息的時間標(biāo)識(參考資料:[url=http://www.52im.net/thread-3008-1-1.html#40]http://www.52im.net/thread-3008-1-1.html#40[/url])
if(theMessage.date - previousMessage.date > MessagesProvider.CHATTING_MESSAGE_SHOW_TIME_INTERVAL)
theMessage.showTopTime = true;
}
}
}
IDataSource實(shí)現(xiàn)類 (詳見 /entry/src/main/ets/pages/utils/MessagesDataSource.ets):
/**
* 聊天界面(ChatPage.ets)中的List列表對應(yīng)的數(shù)據(jù)源實(shí)現(xiàn)類(負(fù)責(zé)聊天消息數(shù)據(jù)的UI顯示)。
*
* 注意:本類中的數(shù)據(jù)來源為全局消息緩存管理類 MessageProvider 中緩存消息集合的對象引用(淺拷貝),相當(dāng)于共用同一個緩存,無需單
* 獨(dú)維護(hù)數(shù)據(jù),實(shí)現(xiàn)了聊天消息數(shù)據(jù)的管理(MessageProvider負(fù)責(zé))和UI界面顯示(MessagesDataSource負(fù)責(zé))的解偶。
*
* @author JackJang
* @since 1.0
*/
export default class MessagesDataSource extends BasicDataSource<Message> {
/** 引用全局消息緩存管理類 MessageProvider 中緩存消息集合(淺拷貝)*/
private messages: Array<Message> = IMClientManager.getInstance().getMessageProvider().getMessages();
notifyDataReload(): void {
super.notifyDataReload();
}
totalCount(): number {
return this.messages.length
}
getData(index: number): Message {
return this.messages[index]
}
/**
* 在List中使用LazyForEach時,響應(yīng)式ui需要key變化才會更新,本方法就是按可變的內(nèi)容計(jì)算key,從而在DataSource更新時,
* 能讓ui感知到,不然UI是不會刷新顯示的。
*
* @param m 消息對象
* @returns 計(jì)算出的key
*/
static messageItemKey(m: Message) {
// 優(yōu)化點(diǎn):給更新的消息對象加個最近更新時間戳,這應(yīng)該是個更通用的key計(jì)算項(xiàng),不然一旦變更內(nèi)容多了,這個key的計(jì)算就不那么優(yōu)雅了
return m.msgType + '-' + m.fingerPrintOfProtocal + '-' + m.sendStatus;
}
}
12、技術(shù)要點(diǎn)5:關(guān)于網(wǎng)絡(luò)通信層與UI層的聯(lián)動
HarmonyChat中的網(wǎng)絡(luò)通信層與UI層的聯(lián)動,主要是通過MobileIMSDK鴻蒙客戶端SDK的事件通知實(shí)現(xiàn)的聯(lián)動,從而解決了應(yīng)用層與通信層的代碼解偶。
MobileIMSDK鴻蒙客戶端SDK提供的事件有下面這些:
export default class SocketEvent {
/** 網(wǎng)絡(luò)事件:登錄連接或掉線重連響應(yīng)反饋 */
static readonly SOCKET_EVENT_ON_LOGIN_RESPONSE: string;
/** 網(wǎng)絡(luò)事件:網(wǎng)絡(luò)斷開(掉線了) */
static readonly SOCKET_EVENT_ON_LINK_CLOSE: string;
/** 網(wǎng)絡(luò)事件:收到新的消息 */
static readonly SOCKET_EVENT_ON_RECIEVE_MESSAGE: string;
/** 網(wǎng)絡(luò)事件:服務(wù)端反饋的錯誤信息(這種錯誤出現(xiàn)即表示連接不可恢復(fù),SDK框架將會自動進(jìn)入重連動作) */
static readonly SOCKET_EVENT_ON_ERROR_RESPONSE: string;
/** 網(wǎng)絡(luò)事件:發(fā)出的消息沒有成功被送達(dá)(沒有收到應(yīng)答確認(rèn)包) */
static readonly SOCKET_EVENT_MESSAGE_LOST: string;
/** 網(wǎng)絡(luò)事件:發(fā)出的消息已成功被送達(dá)(收到應(yīng)答確認(rèn)包) */
static readonly SOCKET_EVENT_MESSAGE_BE_RECIEVED: string;
/** 網(wǎng)絡(luò)事件:正在嘗試掉線重連動作 */
static readonly SOCKET_EVENT_RECONNECT_ATTEMPT: string;
/** 網(wǎng)絡(luò)事件:心跳包(客戶端發(fā)出的) */
static readonly SOCKET_EVENT_PING: string;
/** 網(wǎng)絡(luò)事件:心跳包(客戶端收到的) */
static readonly SOCKET_EVENT_PONG: string;
/** 網(wǎng)絡(luò)事件:客戶端已被強(qiáng)行踢出 */
static readonly SOCKET_EVENT_KICKOUT: string;
}
HarmonyChat中通過監(jiān)聽以上事件并處理后,拋給UI應(yīng)用層的事件就非常簡單了,暫時僅僅需要以下幾個事件就實(shí)現(xiàn)了當(dāng)前的UI刷新等任務(wù):
/**
* 應(yīng)用層的各種通知事件類型,這些事件主要用于通知UI界面的更新等。
*
* @author Jack Jiang([url=http://www.52im.net/thread-2792-1-1.html]http://www.52im.net/thread-2792-1-1.html[/url])
*/
export default class UIEvent {
/** UI事件:登錄或掉線重連完成 */
static readonly UIEVENT_onIMAfterLoginComplete: string = "uievent.onIMAfterLoginComplete";
/** UI事件:掉線了 */
static readonly UIEVENT_onIMDisconnected: string = "uievent.onIMDisconnected";
/** UI事件:心跳了一次(發(fā)出的) */
static readonly UIEVENT_onIMPing: string = "uievent.onIMPing";
/** UI事件:心跳了一次(收到的應(yīng)答包) */
static readonly UIEVENT_onIMPong: string = "uievent.onIMPong";
/** UI事件:你被踢了 */
static readonly UIEVENT_onKickout: string = "uievent.onKickout";
/** UI事件:增加了聊天消息 */
static readonly UIEVENT_messageAdded = 'uievent.messageAdded';
/** UI事件:更新了聊天消息(單條聊天消息) */
static readonly UIEVENT_messageUpdate = 'uievent.messageUpdate';
/** UI事件:更新了聊天消息(多條聊天消息) */
static readonly UIEVENT_messagesUpdate = 'uievent.messagesUpdate';
}
HarmonyChat中注冊和監(jiān)聽這些事件的具體代碼邏輯位于 /entry/src/main/ets/pages/utils/IMClientManager.ets類中,代碼有點(diǎn)長就不貼了,請自行查看。
13、相關(guān)資料
[1] 華為鴻蒙Next官方開發(fā)資料
[2] MobileIMSDK開源框架的API文檔
[3] MobileIMSDK開源IM框架源碼(Github地址點(diǎn)此)
[4] MobileIMSDK-鴻蒙Next端開發(fā)手冊(* 推薦)
[5] MobileIMSDK-服務(wù)端部署手冊
14、更多IM學(xué)習(xí)和實(shí)踐代碼
《一種Android端IM智能心跳算法的設(shè)計(jì)與實(shí)現(xiàn)探討(含樣例代碼)》
《Java NIO基礎(chǔ)視頻教程、MINA視頻教程、Netty快速入門視頻 [有源碼]》
《輕量級即時通訊框架MobileIMSDK的iOS源碼(開源版)[附件下載]》
《開源IM工程“蘑菇街TeamTalk”2015年5月前未刪減版完整代碼 [附件下載]》
《微信本地?cái)?shù)據(jù)庫破解版(含iOS、Android),僅供學(xué)習(xí)研究 [附件下載]》
《NIO框架入門(一):服務(wù)端基于Netty4的UDP雙向通信Demo演示 [附件下載]》
《NIO框架入門(二):服務(wù)端基于MINA2的UDP雙向通信Demo演示 [附件下載]》
《NIO框架入門(三):iOS與MINA2、Netty4的跨平臺UDP雙向通信實(shí)戰(zhàn) [附件下載]》
《NIO框架入門(四):Android與MINA2、Netty4的跨平臺UDP雙向通信實(shí)戰(zhàn) [附件下載]》
《用于IM中圖片壓縮的Android工具類源碼,效果可媲美微信 [附件下載]》
《高仿Android版手機(jī)QQ可拖拽未讀數(shù)小氣泡源碼 [附件下載]》
《一個WebSocket實(shí)時聊天室Demo:基于node.js+socket.io [附件下載]》
《Android聊天界面源碼:實(shí)現(xiàn)了聊天氣泡、表情圖標(biāo)(可翻頁) [附件下載]》
《高仿Android版手機(jī)QQ首頁側(cè)滑菜單源碼 [附件下載]》
《開源libco庫:單機(jī)千萬連接、支撐微信8億用戶的后臺框架基石 [源碼下載]》
《分享java AMR音頻文件合并源碼,全網(wǎng)最全》
《一個基于MQTT通信協(xié)議的完整Android推送Demo [附件下載]》
《Android版高仿微信聊天界面源碼 [附件下載]》
《高仿手機(jī)QQ的Android版鎖屏聊天消息提醒功能 [附件下載]》
《高仿iOS版手機(jī)QQ錄音及振幅動畫完整實(shí)現(xiàn) [源碼下載]》
《Android端社交應(yīng)用中的評論和回復(fù)功能實(shí)戰(zhàn)分享[圖文+源碼]》
《Android端IM應(yīng)用中的@人功能實(shí)現(xiàn):仿微博、QQ、微信,零入侵、高可擴(kuò)展[圖文+源碼]》
《仿微信的IM聊天時間顯示格式(含iOS/Android/Web實(shí)現(xiàn))[圖文+源碼]》
《Android版仿微信朋友圈圖片拖拽返回效果 [源碼下載]》
《跟著源碼學(xué)IM(一):手把手教你用Netty實(shí)現(xiàn)心跳機(jī)制、斷線重連機(jī)制》
《跟著源碼學(xué)IM(二):自已開發(fā)IM很難?手把手教你擼一個Andriod版IM》
《跟著源碼學(xué)IM(三):基于Netty,從零開發(fā)一個IM服務(wù)端》
《跟著源碼學(xué)IM(四):拿起鍵盤就是干,教你徒手開發(fā)一套分布式IM系統(tǒng)》
《跟著源碼學(xué)IM(五):正確理解IM長連接、心跳及重連機(jī)制,并動手實(shí)現(xiàn)》
《跟著源碼學(xué)IM(六):手把手教你用Go快速搭建高性能、可擴(kuò)展的IM系統(tǒng)》
《跟著源碼學(xué)IM(七):手把手教你用WebSocket打造Web端IM聊天》
《跟著源碼學(xué)IM(八):萬字長文,手把手教你用Netty打造IM聊天》
《跟著源碼學(xué)IM(九):基于Netty實(shí)現(xiàn)一套分布式IM系統(tǒng)》
《跟著源碼學(xué)IM(十):基于Netty,搭建高性能IM集群(含技術(shù)思路+源碼)》
《跟著源碼學(xué)IM(十一):一套基于Netty的分布式高可用IM詳細(xì)設(shè)計(jì)與實(shí)現(xiàn)(有源碼)》
《跟著源碼學(xué)IM(十二):基于Netty打造一款高性能的IM即時通訊程序》
《手把手教你實(shí)現(xiàn)網(wǎng)頁端社交應(yīng)用中的@人功能:技術(shù)原理、代碼示例等》
《SpringBoot集成開源IM框架MobileIMSDK,實(shí)現(xiàn)即時通訊IM聊天功能》
《基于Netty,徒手?jǐn)]IM(一):IM系統(tǒng)設(shè)計(jì)篇》