什麼都別說, 先看代碼:
- //構造函數
- protected PacketReader(final XMPPConnection connection) {
- this.connection = connection;
- this.init();
- }
- /**
- * Initializes the reader in order to be used. The reader is initialized
- * during the first connection and when reconnecting due to an abruptly
- * disconnection.
- */
- protected void init() {
- done = false;
- connectionID = null;
- //開闢一個線程, 解析收到的數據包
- readerThread = new Thread() {
- public void run() {
- parsePackets(this);
- }
- };
- readerThread.setName("Smack Packet Reader (" + connection.connectionCounterValue + ")");
- readerThread.setDaemon(true);
- // Create an executor to deliver incoming packets to listeners. We'll
- // use a single
- // thread with an unbounded queue.
- listenerExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
- public Thread newThread(Runnable runnable) {
- Thread thread = new Thread(runnable, "Smack Listener Processor ("
- + connection.connectionCounterValue + ")");
- thread.setDaemon(true);
- return thread;
- }
- });
- resetParser();
- }
- /**
- * Parse top-level packets in order to process them further.
- *
- * @param thread the thread that is being used by the reader to parse
- * incoming packets.
- */
- private void parsePackets(Thread thread) {
- try {
- int eventType = parser.getEventType();
- do {
- if (eventType == XmlPullParser.START_TAG) {
- if (parser.getName().equals("message")) {
- processPacket(PacketParserUtils.parseMessage(parser));
- } else if (parser.getName().equals("iq")) {
- processPacket(PacketParserUtils.parseIQ(parser, connection));
- } else if (parser.getName().equals("presence")) {
- processPacket(PacketParserUtils.parsePresence(parser));
- }
構造函數和init()方法PacketWriter一樣, 不多說了. 直接看parsePackets(). 在parsePackets()是直接調用processPacket()方法解析, 我們再來看processPacket()方法:
- /**
- * Processes a packet after it's been fully parsed by looping through the
- * installed packet collectors and listeners and letting them examine the
- * packet to see if they are a match with the filter.
- *
- * @param packet the packet to process.
- */
- private void processPacket(Packet packet) {
- if (packet == null) {
- return;
- }
- // Loop through all collectors and notify the appropriate ones.
- for (PacketCollector collector : connection.getPacketCollectors()) {
- collector.processPacket(packet);
- }
- // Deliver the incoming packet to listeners.
- listenerExecutor.submit(new ListenerNotification(packet));
- }
- /**
- * A runnable to notify all listeners of a packet.
- */
- private class ListenerNotification implements Runnable {
- private Packet packet;
- public ListenerNotification(Packet packet) {
- this.packet = packet;
- }
- public void run() {
- //循環讀取註冊了的監聽器並通知處理packet
- for (ListenerWrapper listenerWrapper : connection.recvListeners.values()) {
- listenerWrapper.notifyListener(packet);
- }
- }
- }
在ListenerNotification的run方法中, 是循環讀取connection.recvListeners.values()獲取ListenerWrapper
.
那麼ListenerWrapper 是什麼呢? 我們首先來看這裏connection.recvListeners.values(), 這connection實際上
是一個XMPPConnection的一個實例, 而XMPPConnection繼承了Connection, recvListeners實際上是Connection
的一個成員變量. 然後再來看ListenerWrapper類:
- /**
- * A wrapper class to associate a packet filter with a listener.
- *
- */
- protected static class ListenerWrapper {
- private PacketListener packetListener;
- private PacketFilter packetFilter;
- /**
- * Create a class which associates a packet filter with a listener.
- *
- * @param packetListener the packet listener.
- * @param packetFilter the associated filter or null if it listen for
- * all packets.
- */
- public ListenerWrapper(PacketListener packetListener, PacketFilter packetFilter) {
- this.packetListener = packetListener;
- this.packetFilter = packetFilter;
- }
- /**
- * Notify and process the packet listener if the filter matches the
- * packet.
- * @param packet the packet which was sent or received.
- */
- public void notifyListener(Packet packet) {
- if (packetFilter == null || packetFilter.accept(packet)) {
- packetListener.processPacket(packet);
- }
- }
- }
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 接口決定哪個特別的將會被傳遞到PacketCollector或PacketListener。filter package包中有許多預定義的過濾器。
packetListener 是一個能夠處理隨時可能到了的packet監聽器,packetFilter能夠判斷packet是否由該packetListener處理
是的話則調用processPacket()方法處理packet. 至此整個過程處理完成