smack 源码分析- PacketWriter (android上实现长连接) 介绍完PacketWriter 之后, 接下来分析PacketReader. PacketReader的作用主要用来接收云端推送的消息并解析然后调用相应的监听器完成相关的操作.
什么都别说, 先看代码:
-
- protected PacketReader(final XMPPConnection connection) {
- this.connection = connection;
- this.init();
- }
-
-
-
-
-
-
-
- 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);
-
-
-
-
- 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();
- }
-
-
-
-
-
-
-
-
-
-
- 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()方法:
-
-
-
-
-
-
-
- private void processPacket(Packet packet) {
- if (packet == null) {
- return;
- }
-
-
- for (PacketCollector collector : connection.getPacketCollectors()) {
- collector.processPacket(packet);
- }
-
-
- listenerExecutor.submit(new ListenerNotification(packet));
- }
在processPacket()的最后一行是通过ExecutorService类型的一个listenerExecutor实例执行一个线程ListenerNotification完成的. 接下来:
-
-
-
- private class ListenerNotification implements Runnable {
-
- private Packet packet;
-
- public ListenerNotification(Packet packet) {
- this.packet = packet;
- }
-
- public void run() {
-
- 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类:
-
-
-
-
- protected static class ListenerWrapper {
-
- private PacketListener packetListener;
-
- private PacketFilter packetFilter;
-
-
-
-
-
-
-
-
- public ListenerWrapper(PacketListener packetListener, PacketFilter packetFilter) {
- this.packetListener = packetListener;
- this.packetFilter = packetFilter;
- }
-
-
-
-
-
-
- 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. 至此整个过程处理完成