smack 源码分析- PacketWriter (android上实现长连接) 介绍完PacketWriter 之后, 接下来分析PacketReader.PacketReader的作用主要用来接收云端推送的消息并解析然后调用相应的监听器完成相关的操作.

什么都别说, 先看代码:

//构造函数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));    }

在processPacket()的最后一行是通过ExecutorService类型的一个listenerExecutor实例执行一个线程ListenerNotification完成的. 接下来:

 /**     * 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收集器和监听器。

org.jivesoftware.smack.filter.PacketFilter 接口决定哪个特别的将会被传递 PacketCollectorPacketListener。org.jivesoftware.smack.filter package包中有许多预定义的过滤器。


packetListener 是一个能够处理随时可能到了的packet监听器, packetFilter能够判断packet是否由该packetListener处理

是的话则调用processPacket()方法处理packet. 至此整个过程处理完成

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. android上一些方法的区别和用法的注意事项
  5. android实现字体闪烁动画的方法
  6. Android中dispatchDraw分析
  7. Android四大基本组件介绍与生命周期
  8. Android(安卓)MediaPlayer 常用方法介绍
  9. 在Fragment中设置控件点击方法,执行失败。

随机推荐

  1. Android实现开机自启动无效问题
  2. Validates using resource IDs in a swit
  3. Android屏幕中隐藏标题栏
  4. ant 打包android应用
  5. android 中文 api (71) —— BluetoothServ
  6. TTS源码解析
  7. android移植详解
  8. 玩转Android---UI篇---ImageButton(带图
  9. 给作为安卓开发新手的自己的几点建议(摘抄
  10. Android中贪吃蛇游戏的学习(五)