<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jack Jiang

    我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
    posts - 494, comments - 13, trackbacks - 0, articles - 1

    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ì)篇



    作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
    出處:http://www.52im.net/space-uid-1.html
    交流:歡迎加入即時通訊開發(fā)交流群 215891622
    討論:http://www.52im.net/
    Jack Jiang同時是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
    本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處(也可前往 我的52im.net 找到我)。


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 成年性生交大片免费看| 亚洲av产在线精品亚洲第一站| 免费福利网站在线观看| 野花香高清视频在线观看免费 | 亚洲av永久无码精品网站 | 国产精品免费观看调教网| 黄色a级片免费看| 亚洲高清一区二区三区电影| 91亚洲自偷在线观看国产馆| 亚洲国产精品无码久久久蜜芽| 午夜亚洲福利在线老司机| 女人18一级毛片免费观看| 无码人妻一区二区三区免费手机 | 波多野结衣免费一区视频 | 亚洲精品狼友在线播放| 亚洲色偷偷综合亚洲AVYP| 中文字幕亚洲电影| 国产亚洲一区二区三区在线不卡| 亚洲午夜无码AV毛片久久| 亚洲乱码国产一区网址| 自拍偷自拍亚洲精品被多人伦好爽 | 免费国产草莓视频在线观看黄| 亚洲av午夜国产精品无码中文字| 亚洲乱码日产精品一二三| 亚洲人成电影网站色www| 亚洲乱码av中文一区二区| 久久久久久亚洲av无码蜜芽| 亚洲av综合日韩| 一级黄色毛片免费看| 国产又黄又爽又大的免费视频 | 日本激情猛烈在线看免费观看| 国产一区二区三区亚洲综合| 久久WWW免费人成—看片| 成年女人A毛片免费视频| 久久久久高潮毛片免费全部播放| **aaaaa毛片免费| 国产高清免费在线| 中文字幕亚洲综合久久菠萝蜜| 亚洲天堂视频在线观看| 亚洲精品永久在线观看| 好猛好深好爽好硬免费视频|