smack 源碼分析- PacketReader (android上實現長連接)【3】


smack 源碼分析- PacketWriter (android上實現長連接) 介紹完PacketWriter 之後, 接下來分析PacketReader. PacketReader的作用主要用來接收雲端推送的消息並解析然後調用相應的監聽器完成相關的操作.

什麼都別說, 先看代碼:

[java] view plaincopy
  1. //構造函數  
  2. protected PacketReader(final XMPPConnection connection) {  
  3.         this.connection = connection;  
  4.         this.init();  
  5. }  
  6.   
  7.   
  8.  /** 
  9.      * Initializes the reader in order to be used. The reader is initialized 
  10.      * during the first connection and when reconnecting due to an abruptly 
  11.      * disconnection. 
  12.      */  
  13.     protected void init() {  
  14.         done = false;  
  15.         connectionID = null;  
  16.   
  17.         //開闢一個線程, 解析收到的數據包  
  18.         readerThread = new Thread() {  
  19.             public void run() {  
  20.                 parsePackets(this);  
  21.             }  
  22.         };  
  23.         readerThread.setName("Smack Packet Reader (" + connection.connectionCounterValue + ")");  
  24.         readerThread.setDaemon(true);  
  25.   
  26.         // Create an executor to deliver incoming packets to listeners. We'll  
  27.         // use a single  
  28.         // thread with an unbounded queue.  
  29.         listenerExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {  
  30.   
  31.             public Thread newThread(Runnable runnable) {  
  32.                 Thread thread = new Thread(runnable, "Smack Listener Processor ("  
  33.                         + connection.connectionCounterValue + ")");  
  34.                 thread.setDaemon(true);  
  35.                 return thread;  
  36.             }  
  37.         });  
  38.   
  39.         resetParser();  
  40.     }  
  41.   
  42.   
  43.   
  44.   
  45.  /** 
  46.      * Parse top-level packets in order to process them further. 
  47.      *  
  48.      * @param thread the thread that is being used by the reader to parse 
  49.      *            incoming packets. 
  50.      */  
  51.     private void parsePackets(Thread thread) {  
  52.         try {  
  53.             int eventType = parser.getEventType();  
  54.             do {  
  55.   
  56.                 if (eventType == XmlPullParser.START_TAG) {  
  57.                     if (parser.getName().equals("message")) {  
  58.                         processPacket(PacketParserUtils.parseMessage(parser));  
  59.                     } else if (parser.getName().equals("iq")) {  
  60.                         processPacket(PacketParserUtils.parseIQ(parser, connection));  
  61.                     } else if (parser.getName().equals("presence")) {  
  62.                         processPacket(PacketParserUtils.parsePresence(parser));  
  63.                     }  

構造函數和init()方法PacketWriter一樣, 不多說了. 直接看parsePackets(). 在parsePackets()是直接調用processPacket()方法解析, 我們再來看processPacket()方法:

[java] view plaincopy
  1. /** 
  2.      * Processes a packet after it's been fully parsed by looping through the 
  3.      * installed packet collectors and listeners and letting them examine the 
  4.      * packet to see if they are a match with the filter. 
  5.      *  
  6.      * @param packet the packet to process. 
  7.      */  
  8.     private void processPacket(Packet packet) {  
  9.         if (packet == null) {  
  10.             return;  
  11.         }  
  12.   
  13.         // Loop through all collectors and notify the appropriate ones.  
  14.         for (PacketCollector collector : connection.getPacketCollectors()) {  
  15.             collector.processPacket(packet);  
  16.         }  
  17.   
  18.         // Deliver the incoming packet to listeners.  
  19.         listenerExecutor.submit(new ListenerNotification(packet));  
  20.     }  



在processPacket()的最後一行是通過ExecutorService類型的一個listenerExecutor實例執行一個線程ListenerNotification完成的. 接下來: 

[java] view plaincopy
  1. /** 
  2.      * A runnable to notify all listeners of a packet. 
  3.      */  
  4.     private class ListenerNotification implements Runnable {  
  5.   
  6.         private Packet packet;  
  7.   
  8.         public ListenerNotification(Packet packet) {  
  9.             this.packet = packet;  
  10.         }  
  11.   
  12.         public void run() {  
  13.             //循環讀取註冊了的監聽器並通知處理packet  
  14.             for (ListenerWrapper listenerWrapper : connection.recvListeners.values()) {  
  15.                   
  16.                 listenerWrapper.notifyListener(packet);  
  17.             }  
  18.         }  
  19.     }  

在ListenerNotification的run方法中,  是循環讀取connection.recvListeners.values()獲取ListenerWrapper
.

那麼ListenerWrapper 是什麼呢? 我們首先來看這裏connection.recvListeners.values(), 這connection實際上

是一個XMPPConnection的一個實例, 而XMPPConnection繼承了Connection, recvListeners實際上是Connection

的一個成員變量. 然後再來看ListenerWrapper類:


[java] view plaincopy
  1. /** 
  2.      * A wrapper class to associate a packet filter with a listener. 
  3.      * 
  4.      */  
  5.     protected static class ListenerWrapper {  
  6.   
  7.         private PacketListener packetListener;  
  8.   
  9.         private PacketFilter packetFilter;  
  10.   
  11.         /** 
  12.          * Create a class which associates a packet filter with a listener. 
  13.          *  
  14.          * @param packetListener the packet listener. 
  15.          * @param packetFilter the associated filter or null if it listen for 
  16.          *            all packets. 
  17.          */  
  18.         public ListenerWrapper(PacketListener packetListener, PacketFilter packetFilter) {  
  19.             this.packetListener = packetListener;  
  20.             this.packetFilter = packetFilter;  
  21.         }  
  22.   
  23.         /** 
  24.          * Notify and process the packet listener if the filter matches the 
  25.          * packet.  
  26.          * @param packet the packet which was sent or received. 
  27.          */  
  28.         public void notifyListener(Packet packet) {  
  29.             if (packetFilter == null || packetFilter.accept(packet)) {   
  30.                 packetListener.processPacket(packet);  
  31.             }  
  32.         }  
  33.     }  

ListenerWrapper類實際上是一個包裝類, 該類的作用是將packetListener
packetFilter關聯在一起. 那麼

packetListener 和packetFilter分別是什麼嗯, 查看smack幫助文檔可知:


Smack提供靈活的框架來通過兩種構造處理收到的 packet:

  • org.jivesoftware.smack.PacketCollector —— 一個讓您同步等待新packet的類。
  • org.jivesoftware.smack.PacketListener —— 一個異步通知您引入的packet的接口。

packet監聽器用於事件樣式的編程,而packet收集器有一個可以做輪詢和阻塞操作的packet的結果隊列。 所以,當您想對一個有可能隨時到來的packet採取一些操作時,使用packet監聽器;而當您想等待一個特別的packet到來時,使用packet收集器。您可以使用XMPPConnection實例創建packet收集器和監聽器。

PacketFilter 接口決定哪個特別的將會被傳遞PacketCollectorPacketListener。filter package包中有許多預定義的過濾器。


packetListener 是一個能夠處理隨時可能到了的packet監聽器,packetFilter能夠判斷packet是否由該packetListener處理

是的話則調用processPacket()方法處理packet. 至此整個過程處理完成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章