因為我們現(xiàn)在有了本地服務(wù)器利器,且了解了數(shù)據(jù)庫吼肥。實現(xiàn)單聊群聊易如反掌录平。從功能上來說單聊群聊難度是幾乎差不多的,本文詳細的說明單聊實現(xiàn)邏輯缀皱。
一切解題思路都在數(shù)據(jù)庫上斗这。數(shù)據(jù)庫需要設(shè)計的,設(shè)計好了啤斗,很多問題全部迎刃而解表箭。
一、單聊和群聊是不是同一個類型钮莲?
經(jīng)過我深思熟慮免钻,參考之前做的環(huán)信和云信以及騰訊云的源碼,表分開設(shè)計比較好臂痕。
二伯襟、用戶表設(shè)計:
這里還是有一個前提,所有好友的ip段以及ip是固定的握童。假設(shè)不固定后面再說怎么處理姆怪,其實就是個數(shù)組如何初始化的小case。另外,據(jù)我所知每個人不僅有ip稽揭,而且攜帶的藍牙設(shè)備有一個唯一的設(shè)備標識我們成為device id俺附,簡稱did。
單聊或群聊可能需要顯示用戶的頭像昵稱信息溪掀,我們把用戶信息做成一張表事镣,單聊群聊記錄哪個用戶的聊天記錄的時候只需要記錄這個用戶的ip和did信息,到時候根據(jù)ip外鍵關(guān)聯(lián)揪胃。
id: 主鍵自增
ip: 用戶的ip地址
did:用戶的設(shè)備唯一標識號
head_image: 頭像
nick_name: 昵稱
c_time: 個人信息的創(chuàng)建時間戳璃哟,這是更新用戶信息的重要判斷標準。
....其他字段
當我自己在修改我的個人昵稱頭像的時候喊递,更新我自己的表就可以了随闪。不用告訴其他人,因為有的人不在線骚勘,現(xiàn)在告訴他們貌似效率不高铐伴。
三、獲取好友列表
因為好友列表好友的狀態(tài)是時刻變化的俏讹,且在頁面onShow的時候需要請求刷新列表數(shù)據(jù)当宴,我想了下這個列表數(shù)據(jù)不需要保存到數(shù)據(jù)庫(保存也可以你自己決定)。
(1)好友列表是固定的泽疆。如果是ip從10-21户矢,一定是12個人的列表
(2)他們的狀態(tài)可能是時刻變化的。
所有人在好友頁面列表onShow事件中開始獲取好友在線狀態(tài)(列表恒定在,過濾自己)殉疼,以ip=10這個人為例逗嫡。for循環(huán)POST請求10-21的ip的接口:/user/check/online
如果11請求成功,把數(shù)組在線狀態(tài)online置為101
如果12請求被回調(diào)告知失敗株依,把數(shù)組在線狀態(tài)online置為102
......
這樣我們就得到了一個好友列表了驱证。頁面將在點擊刷新按鈕或下一次onShow的時候刷新。
四恋腕、單聊數(shù)據(jù)表設(shè)計:
我們先設(shè)計表抹锄,表好了,功能基本就完成了荠藤。單聊我們使用single_chat表伙单,后面群聊我們使用group_chat表
先思考一個兩個人單聊,需要哪些字段:
id: 主鍵自增
from: 發(fā)送方的ip
to:接受方的ip
message_type: 消息類型哈肖,101文字消息 102語音消息 103圖片消息 104視頻消息 ...
content: 消息具體內(nèi)容吻育,因為全部本質(zhì)是文本消息,所以這里就是統(tǒng)一的簡單的字符串
c_time: 消息的創(chuàng)建時間戳淤井,這個非常重要布疼,將決定了消息的順序摊趾。特別是消息和服務(wù)器同步后保證消息不順序混亂。
五游两、單聊功能實現(xiàn):
目前我ip=10砾层,ip=11在線,ip=12不在線贱案。
(a)與不在線的人聊天:
與不在線的人聊天比較簡單肛炮,點擊進入12的單聊頁面,允許他點進宝踪。因為就算12不在線侨糟,我也可以查看歷史記錄或從服務(wù)器同步數(shù)據(jù)。只是進來如果12不在線瘩燥,發(fā)任何消息都失敗粟害。我們可以簡單點,失敗的消息不記錄數(shù)據(jù)庫颤芬,只有在發(fā)成功的才記錄。
(b)與在線的人聊天:如ip=11
(1)因為所有的消息都是文本消息只有message_type不一樣套鹅,從數(shù)據(jù)庫的角度就只有一種消息一樣站蝠。ip=10向11發(fā)消息后,先把數(shù)據(jù)記錄到數(shù)據(jù)庫卓鹿,然后把數(shù)據(jù)刷新到聊天列表中菱魔。
(2)Ip=11的人收到消息(處理POST請求),一樣先記錄到數(shù)據(jù)庫吟孙,然后刷新到UI澜倦。
(3)進入聊天頁面查看歷史消息直接一個sql+where查詢得到聊天列表。
(c)如何查看更多歷史消息杰妓?
? ? 我喜歡先簡化問題藻治,再來細節(jié)化解決問題。目前我們先簡化問題實現(xiàn)功能巷挥,查詢數(shù)據(jù)庫的時候limit0,500桩卵,數(shù)據(jù)當然在數(shù)據(jù)庫,我們目前只顯示最近的500條聊天記錄倍宾。
(d)如何和服務(wù)器數(shù)據(jù)同步雏节?接口即將寫。
就是上面這200條數(shù)據(jù)高职,在進入聊天列表的時候全部丟給服務(wù)器钩乍,服務(wù)器對比后記錄服務(wù)器不存在的數(shù)據(jù),且將你缺失的數(shù)據(jù)返回怔锌。
????(1)如果返回的list.size=0寥粹,說明服務(wù)器的數(shù)據(jù)你都有变过。
????(2)如果返回的list.size>0,說明服務(wù)器的數(shù)據(jù)你有l(wèi)ist.size條丟失了排作,你插入數(shù)據(jù)庫即可牵啦。不用擔心順序的問題。你查詢的時候c_time會自動給你整理好妄痪。
所以進入聊天列表哈雏,請求服務(wù)器接口,post服務(wù)器成功后插入缺失的數(shù)據(jù)執(zhí)行500條查詢衫生。post失敗后也執(zhí)行500條查詢即可裳瘪。
(e)更新頭像昵稱信息后,好友什么時候獲知最好罪针?
目前我個人感覺彭羹,在用戶發(fā)單聊或群聊消息的時候附帶上自己的個人信息就可以了。用戶收到后泪酱,對比一下from用戶信息的c_time派殷,如果本地沒有這個用戶或本地用戶的c_time和收到的用戶c_time不一致,則更新該用戶的個人信息墓阀。
用戶發(fā)送消息體參考:
message = {
? ? from: 10, //發(fā)送方ip
? ? from_user:{ //完成的用戶模型毡惜,不用想是否費流量,這個問題在局域網(wǎng)和5G時代不是問題了
? ? ? ? ? ? ip: 10,
? ? ? ? ? ? nick_name: "張三" , ?//昵稱
? ? ? ? ? ? head_image: "", //頭像
? ? ? ? ? ? c_time: 1356669887, //用戶信息最后更新時間
? ? ?},
? ? to:11, //接收訪ip
????message_type: 101 //文字消息
? ? content: "hello", //消息內(nèi)容
}