您的位置:首页 > 其它

基于XMPP协议的aSmack源码分析【3】register过程分析

2016-01-21 10:43 330 查看
register过程分析
RegisterTask这个task在运行中,添加了一个监听,上面说道的PacketReader中有一个消息机制,在不停的解析服务器返回的结果,然后将解析过后的包分发给各个监听器(观察者),而register中就注册了一个监听器,比较有意思的是,监听器被注册时还加了一个过滤器,这个过滤器的目的是监听器只接收自己感兴趣的内容,这个设计真的很赞。这样就不必在数据源头PacketReader中对数据进行过滤了,只要后期扩展自己Packet和自己的过滤器,就能达到排除自己不关心的信息的功能。

1 Registration registration = new Registration();
2
3                 PacketFilter packetFilter = new AndFilter(new PacketIDFilter(
4                         registration.getPacketID()), new PacketTypeFilter(
5                         IQ.class));


其中Registration的类型其实一个IQ的子类,IQ是Packet的子类。
AndFilter是PacketFilter的子类,PacketFilter的种类型有很多,也可以自己扩展,AndFilter就是其中一个、PacketTypeFilter也是、PacketIDFilter也是,
其中PacketTypeFilter的构造方法传入一个IQ.class,其实就是通过这个类文件来过滤packet,这个PacketTypeFilter就是要设置关心的Packet,这里面它告诉监听器,只接收类型为IQ的Packet,这些Filter中都有一个关键方法,accept(Packet packet).这个accept方法每个Filter的实现方式都不一样,我们可可以扩展自己的Filter并且重写这个方法,最有意思的是AndFilter这个类,他的构造方法传入的是一个动态数组,类型为PacketFilter,你可以传入你需要的过滤器,将他们当成组合条件使用来过滤Packet,这个就是典型的装饰设计模式和职责链模式的组合使用。

注册监听器

PacketListener packetListener = new PacketListener() {
//这一部分就是监听器接收到Packet后执行的后续操作
public void processPacket(Packet packet) {
Log.d("RegisterTask.PacketListener",
"processPacket().....");
Log.d("RegisterTask.PacketListener", "packet="
+ packet.toXML());

if (packet instanceof IQ) {
IQ response = (IQ) packet;
if (response.getType() == IQ.Type.ERROR) {
if (!response.getError().toString().contains(
"409")) {
Log.e(LOGTAG,
"Unknown error while registering XMPP account! "
+ response.getError()
.getCondition());
}
} else if (response.getType() == IQ.Type.RESULT) {
xmppManager.setUsername(newUsername);
xmppManager.setPassword(newPassword);
Log.d(LOGTAG, "username=" + newUsername);
Log.d(LOGTAG, "password=" + newPassword);

Editor editor = sharedPrefs.edit();
editor.putString(Constants.XMPP_USERNAME,
newUsername);
editor.putString(Constants.XMPP_PASSWORD,
newPassword);
editor.commit();
Log
.i(LOGTAG,
"Account registered successfully");
//执行task
xmppManager.runTask();
}
}
}
};

connection.addPacketListener(packetListener, packetFilter);


addPacketListener方法传入一个监听器和过滤器,看一下内部

/**
* Registers a packet listener with this connection. A packet filter determines
* which packets will be delivered to the listener. If the same packet listener
* is added again with a different filter, only the new filter will be used.
*
* @param packetListener the packet listener to notify of new received packets.
* @param packetFilter   the packet filter to use.
*/
public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter) {
if (packetListener == null) {
throw new NullPointerException("Packet listener is null.");
}
ListenerWrapper wrapper = new ListenerWrapper(packetListener, packetFilter);
recvListeners.put(packetListener, wrapper);
}


可以看到,监听器和过滤器被 ListenerWrapper 再次封装,后续的recvListeners这个集合将ListenerWrapper收入囊中,好整个注册过程完毕,就等待接收信息了,那么发送信息的地方在什么地方呢?分析connect过程时,上面的PacketReader中已经开始循环发送了,代码如下
listenerExecutor.submit(new ListenerNotification(packet));其中ListenerNotification是个Runnable

/**
* A runnable to notify all listeners of a packet.
*/
private class ListenerNotification implements Runnable {

private Packet packet;

public ListenerNotification(Packet packet) {
this.packet = packet;
}

4000
public void run() {
for (ListenerWrapper listenerWrapper : connection.recvListeners.values()) {
listenerWrapper.notifyListener(packet);
}
}
}


而listenerWrapper的notifyListener(packet)内部,使用了传入的过滤器对Packet进行了过滤

/**
* 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);
}


而具体的过滤机制还是转调了传入的过滤器本身的过滤方式accept,非常的灵活。过滤完的Packet将被发送出去

这个方法connection.sendPacket(registration);将一个Registration对象发了出去,

public void sendPacket(Packet packet) {
if (!isConnected()) {
throw new IllegalStateException("Not connected to server.");
}
if (packet == null) {
throw new NullPointerException("Packet is null.");
}
packetWriter.sendPacket(packet);
}


内部转调的是 packetWriter.sendPacket(packet);以前提到过PacketWirter中有两个循环机制,其中一个就是在不停的访问队列来获取Packet,而这个sendPacket方法就是将消息写入队列中供消费者使用。

/**
* Sends the specified packet to the server.
*
* @param packet the packet to send.
*/
public void sendPacket(Packet packet) {
if (!done) {
// Invoke interceptors for the new packet that is about to be sent. Interceptors
// may modify the content of the packet.
//内部执行了一个发送数据源的动作,也是为某些监听器对象服务的interceptorWrapper.notifyListener(packet);
connection.firePacketInterceptors(packet);

try {
//将一个Packet对象放入到阻塞队列中,在上面的witerPacket方法中的wile循环中发送出去
queue.put(packet);
}
catch (InterruptedException ie) {
ie.printStackTrace();
return;
}
synchronized (queue) {
queue.notifyAll();
}

// Process packet writer listeners. Note that we're using the sending
// thread so it's expected that listeners are fast.
connection.firePacketSendingListeners(packet);
}
}


其实,注册的过程就是在注册监听,这样在有消息发出时,才可以根据业务需求对消息进行接收和处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: