摘要:本來是想直接深入到的核心層去看的,但是發(fā)現(xiàn)其實上面的部分還有好些沒有分析到,因此回來繼續(xù)分析。另外一個,是專用于統(tǒng)計的,我們暫時不去關(guān)注。具體的內(nèi)容我會在后面的核心層分析的時候指出。準備下一篇進行的核心層分析吧。
本來是想直接深入到mars的核心層去看的,但是發(fā)現(xiàn)其實上面的samples部分還有好些沒有分析到,因此回來繼續(xù)分析。
ConversationActivity這個類中實際上還做了很多的工作,在onCreate中:
final MainService mainService = new MainService(); MarsServiceProxy.setOnPushMessageListener(BaseConstants.CGIHISTORY_CMDID, mainService); MarsServiceProxy.setOnPushMessageListener(BaseConstants.CONNSTATUS_CMDID, mainService); MarsServiceProxy.setOnPushMessageListener(BaseConstants.FLOW_CMDID, mainService); MarsServiceProxy.setOnPushMessageListener(BaseConstants.PUSHMSG_CMDID, mainService); MarsServiceProxy.setOnPushMessageListener(BaseConstants.SDTRESULT_CMDID, mainService);
這里出現(xiàn)了一個MainService,我們來看看:
/mars-master/samples/android/marsSampleChat/app/src/main/java/com/tencent/mars/sample/core/MainService.java
public class MainService implements PushMessageHandler { public static String TAG = "Mars.Sample.MainService"; private Thread recvThread; private LinkedBlockingQueuepushMessages = new LinkedBlockingQueue<>(); private BusinessHandler[] handlers = new BusinessHandler[]{ new MessageHandler(), new StatisticHandler() }; public MainService() { this.start(); } public void start() { if (recvThread == null) { recvThread = new Thread(pushReceiver, "PUSH-RECEIVER"); recvThread.start(); } } private final Runnable pushReceiver = new Runnable() { @Override public void run() { while (true) { try { PushMessage pushMessage = pushMessages.take(); if (pushMessage != null) { for (BusinessHandler handler : handlers) { if (handler.handleRecvMessage(pushMessage)) { break; } } } } catch (InterruptedException e) { e.printStackTrace(); try { Thread.sleep(500); } catch (InterruptedException e1) { // } } } } }; @Override public void process(PushMessage message) { pushMessages.offer(message); } }
1.啟動了一個接受者線程pushReceiver; 2.pushReceiver從LinkedBlockingQueue的pushMessages中不斷獲取message,然后通知到handlers的每個成員中,handlers是這樣定義的:
private BusinessHandler[] handlers = new BusinessHandler[]{ new MessageHandler(), new StatisticHandler() };
繼續(xù)往下看MessageHandler: /mars-master/samples/android/marsSampleChat/app/src/main/java/com/tencent/mars/sample/core/MessageHandler.java
public class MessageHandler extends BusinessHandler{ public static String TAG = MessageHandler.class.getSimpleName(); @Override public boolean handleRecvMessage(PushMessage pushMessage) { switch (pushMessage.cmdId) { case Constants.PUSHCMD: { try { Messagepush.MessagePush message = Messagepush.MessagePush.parseFrom(pushMessage.buffer); Intent intent = new Intent(); intent.setAction(Constants.PUSHACTION); intent.putExtra("msgfrom", message.from); intent.putExtra("msgcontent", message.content); intent.putExtra("msgtopic", message.topic); SampleApplicaton.getContext().sendBroadcast(intent); } catch (InvalidProtocolBufferNanoException e) { Log.e(TAG, "%s", e.toString()); } } return true; default: break; } return false; } }
如果是Constants.PUSHCMD類型的message,那么就發(fā)送一個廣播。這個廣播實際上會由Mars核心部分接收到,但是傳遞的intent參數(shù)其實沒有意義,核心部分只是根據(jù)每次的pushcmd進行網(wǎng)絡(luò)狀態(tài)的檢查而已,這些后話我們在分析核心的時候再說。
另外一個StatisticHandler,是專用于統(tǒng)計的,我們暫時不去關(guān)注。
讓我們回到ConversationActivity,在MainService的new之后,會調(diào)用MarsServiceProxy.setOnPushMessageListener多次,設(shè)置監(jiān)聽,我們來看看MarsServiceProxy里面如何運轉(zhuǎn):
public static void setOnPushMessageListener(int cmdId, PushMessageHandler pushMessageHandler) { if (pushMessageHandler == null) { inst.pushMessageHandlerHashMap.remove(cmdId); } else { inst.pushMessageHandlerHashMap.put(cmdId, pushMessageHandler); } }
添加了監(jiān)聽到一個支持高并發(fā)的hashmap中:
private ConcurrentHashMappushMessageHandlerHashMap = new ConcurrentHashMap<>(); private MarsPushMessageFilter filter = new MarsPushMessageFilter.Stub() { @Override public boolean onRecv(int cmdId, byte[] buffer) throws RemoteException { PushMessageHandler handler = pushMessageHandlerHashMap.get(cmdId); if (handler != null) { Log.i(TAG, "processing push message, cmdid = %d", cmdId); PushMessage message = new PushMessage(cmdId, buffer); handler.process(message); return true; } else { Log.i(TAG, "no push message listener set for cmdid = %d, just ignored", cmdId); } return false; } };
可以看到,這里創(chuàng)建了一個filter,這個filter在接收到一個cmd后,根據(jù)id查找到PushMessageHandler,然后調(diào)用hander.process,傳遞參數(shù)PushMessage,這個PushMessage實際上又是由cmdid和buffer組成的。這里的cmdid理解為一個指令的類型id即可。再到MainService中的process,其實就是加入PushMessage的一個隊列中等待處理。
回來看filter在何時調(diào)用的吧。
首先在MarsServiceProxy的onServiceConnected:
@Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { Log.d(TAG, "remote mars service connected"); try { service = MarsService.Stub.asInterface(iBinder); service.registerPushMessageFilter(filter); service.setAccountInfo(accountInfo.uin, accountInfo.userName); } catch (Exception e) { service = null; } }
看到了吧,將這個filter注冊到了服務(wù)中。來吧,MarsServiceNative的registerPushMessageFilter:
@Override public void registerPushMessageFilter(MarsPushMessageFilter filter) throws RemoteException { stub.registerPushMessageFilter(filter); }
到了MarsServiceStub里:
@Override public void registerPushMessageFilter(MarsPushMessageFilter filter) throws RemoteException { filters.remove(filter); filters.add(filter); }
加入了filters的隊列中,然后在onPush中有所調(diào)用:
@Override public void onPush(int cmdid, byte[] data) { for (MarsPushMessageFilter filter : filters) { try { if (filter.onRecv(cmdid, data)) { break; } } catch (RemoteException e) { // } } }
這里調(diào)用了每個filter的onRecv方法,這樣就和上面的串起來了吧。那么何時調(diào)用的這個onPush呢,答案在核心mars部分的StnLogic里面,這里規(guī)定了一個ICallBack,里面有onPush,會在適當(dāng)?shù)臅r候調(diào)用。具體的內(nèi)容我會在后面的mars核心層分析的時候指出。
總結(jié)一下:
MainService在一開始啟動,并且啟動專門的線程處理接收到的pushMessage,處理的過程就是調(diào)用之前已經(jīng)準備好的一個handler的隊列的每個項目的handleRecvMessage,其中的MessageHandler會發(fā)送廣播通知mars有pushcmd來了。
另一方面,MainService提供process調(diào)用向message隊列中加入新項目。這個加入的過程調(diào)用在MarsServiceProxy中進行,內(nèi)部生成了一個filter過濾器,并將其注冊到服務(wù)MarsServiceNative中,MarsServiceNative其實也是走的MarsServiceStub,在他里面維護的filter的隊列,并且MarsServiceStub還是底層核心Mars的回調(diào)監(jiān)聽者,在onPush到來的時候,依次調(diào)用filter隊列中的各個項目的onRecv方法來實現(xiàn)通知。在filter的onRecv方法中就實現(xiàn)了handler.process(message),通知到了handler。
現(xiàn)在對于這部分應(yīng)該比較明晰了吧。準備下一篇進行Mars的核心層分析吧。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66977.html
摘要:微信已經(jīng)開源了,但是市面上相關(guān)的文章較少,即使有也是多在于使用等這些,那么這次我希望能夠從這個直接用于底層通訊的部分進行個分析。首先明確下,微信用了的開源協(xié)議庫,來代替和。核心的部分我們先放下,下一篇再深入分析。 微信已經(jīng)開源了mars,但是市面上相關(guān)的文章較少,即使有也是多在于使用xlog等這些,那么這次我希望能夠從stn這個直接用于im底層通訊的部分進行個分析。為了能分析的全面些,...
摘要:執(zhí)行并根據(jù)每個連接的狀態(tài)決定后續(xù)處理,上篇已經(jīng)講過,不再累述。上面的三段處理完畢后,應(yīng)該是數(shù)組中不再有連接才對,這里的保險處理是對數(shù)組再進行檢查。至此跳出,算是整個連接過程完畢了。這里需要逐句分析,首先是。 最近回顧之前的文章,發(fā)現(xiàn)最后一篇有些著急了,很多地方?jīng)]有敘述清楚。這里先做個銜接吧。我們還是以長連接為例,從longlink.cc看起。首先是那個線程函數(shù)__Run:/mars-m...
摘要:作為微信的終端數(shù)據(jù)庫,從開源至今,共迭代了個版本。微信也轉(zhuǎn)向開發(fā)了嗎相信這會是大家非常關(guān)心的問題。不僅微信,國內(nèi)外大部分都還沒有完全轉(zhuǎn)向,但顯然這是個趨勢。另一方面,沒有微信的上線機制的保護和龐大的用戶量的驗證,我們需要確保的穩(wěn)定性。 WCDB 作為微信的終端數(shù)據(jù)庫,從 2017.6 開源至今,共迭代了 5 個版本。我們一直關(guān)注開發(fā)者們的需求,并不斷優(yōu)化性能,新增如全文搜索等常用的功能...
閱讀 1884·2021-09-22 15:29
閱讀 3361·2019-08-30 15:44
閱讀 3570·2019-08-30 15:43
閱讀 1769·2019-08-30 13:48
閱讀 1497·2019-08-29 13:56
閱讀 2483·2019-08-29 12:12
閱讀 977·2019-08-26 11:35
閱讀 1059·2019-08-26 10:25