2020-01-01 tangrambus事件总线学习笔记
tangrambus
常常听同事们说的事件总线,今天研究记录一下
一、结构-2个字典
1,
topic 字典, “主题”
a,b,c,d,e,f
参数topic
2,
class字典, “某一个分类,物以类聚,属于同类的”
a1,a2,a3,a4,a5
参数topic + identifier
二、添加和读取
添加:
注意不是同时两个字典都添加, 带不带iden, 都会添加到其中一个字典里面!
topic->添加到topic字典, 即a,b,c,d,e
topic+iden-》添加到class字典, 即a1, a2, b1, b2, a3, a4
读取:
注意,是在两个字典里面都查一遍, 带不带iden,都会分别在两个字典里面查询一遍!
topic查询
topic+iden查询
topic-> topic字典, 即a,b,c,d,e
topic+iden-》 class字典, 即a1, a2, b1, b2, a3, a4
a=> top字典找到a,执行。 class字典只有a1,a2 key,没有a,所以不执行
a1=>top字典,取a 找到a,执行。 在class字典,有a1 key,所以执行
关于注册
- (void)registerAction:(NSString *)action
ofExecuter:(id)executer
onEventTopic:(NSString *)topic
{
[self registerAction:action ofExecuter:executer onEventTopic:topic fromPosterIdentifier:nil];
}
- (void)registerAction:(NSString *)anAction
ofExecuter:(id)executer
onEventTopic:(NSString *)topic
fromPosterIdentifier:(NSString *)identifier
关于读取
- (void)dispatchEvent:(TangramEvent *)event
{
NSMutableArray *actionList = [[NSMutableArray alloc] init];
NSArray *topicActions = [self.topicIndex actionsOnEvent:event];
if (topicActions && topicActions.count > 0) {
[actionList addObjectsFromArray:topicActions];
}
NSArray *classActions = [self.classIndex actionsOnEvent:event];
if (classActions && classActions.count > 0) {
[actionList addObjectsFromArray:classActions];
}
for (TangramAction *action in actionList) {
if (action && [action isKindOfClass:[TangramAction class]]) {
[action executeWithContext:event.context];
}
}
}
topic字典
- (NSArray *)actionsOnEvent:(TangramEvent *)event
{
return [self.index tm_arrayForKey:event.topic];
}
class字典
- (NSArray *)actionsOnEvent:(TangramEvent *)event
{
NSArray *actions = nil;
if (event.identifier) {
NSString *key = [event.topic stringByAppendingFormat:@"_%@", event.identifier];
actions = [self.index tm_arrayForKey:key];
}
return actions;
}
三、例子
调用
TangramEvent *event = [[TangramEvent alloc] initWithTopic:@"jumpAction" withTangramView:self.inTangramView posterIdentifier:@"QRCodeClick" andPoster:self];
[event setParam:self.rightJumpAction forKey:@"jumpAction"];
[self.tangramBus postEvent:event];
TangramEvent *event = [[TangramEvent alloc] initWithTopic:@"jumpAction" withTangramView:self.inTangramView posterIdentifier:@"OrderCard" andPoster:self];
[event setParam:self.jumpAction forKey:@"jumpAction"];
[self.tangramBus postEvent:event];
##注册
[self.tangramBus registerAction:@"jumpActionHandler:"
ofExecuter:self
onEventTopic:@"jumpAction"];
看看下面运行结果, 会执行3遍方法
bus = [[TangramBus alloc] init];
[bus registerAction:@"aMethod" ofExecuter:self onEventTopic:@"a"];
[bus registerAction:@"aMethod" ofExecuter:self onEventTopic:@"a" fromPosterIdentifier:@"123"];
return YES;
}
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
TangramEvent*event1=[[TangramEvent alloc] initWithTopic:@"a" withTangramView:nil posterIdentifier:@"123" andPoster:self];
[bus postEvent:event1];
TangramEvent*event2=[[TangramEvent alloc] initWithTopic:@"a" withTangramView:nil posterIdentifier:nil andPoster:self];
[bus postEvent:event2];
}
-(void)aMethod{
NSLog(@"aaaaa");
}
打印验证确实与分析一致:
2020-01-01 16:43:21.189880+0800 TangramDemo[3158:1115795] aaaaa
2020-01-01 16:43:21.190447+0800 TangramDemo[3158:1115795] aaaaa
2020-01-01 16:43:21.191254+0800 TangramDemo[3158:1115795] aaaaa
添加了2个字典,
topic字典: a
class字典:a123
a,123命中 a 和 a123
a命中a
所以有3次调用
1、注册一个topic,支持带任何标示的、或者不带标示的event
2、注册一个topic+iden,只可以支持带标示的event
3、一个带标示的event,可能被不带标示的处理,也可被带标示处理
4、一个不带标示的event,只能被不带标示的处理
这里的iden和notificationcenter的obj参数是一样的
topic对标notificationcenter的name
iden对标notificationcenter的object
image.png
给所有订阅者发送
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
anObject,不为空,只收到object的消息
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;
不同在于:消息中心app系统全局单利只有一个;bus可以多个。
四、设计思想
有一件事情, 我不直接去做这件事, 而是将这件事存放在一个机构, 我只负责一个一个往里边存, 存一次,我通知机构一次
机构得到我的通知, 从仓库里面把这件事重新取出来一个, 然后去执行这个事件, 一个一个“取-》做”, 直到把所有事件全部取出来完, 做完.
就这件事来说, 我直接去做不行吗, 还要先存起来,再取出来,再做,事情还是那件事情, 经过容器转一到手, 有什么好处呢?
- (void)postEvent:(TangramEvent *)event
{
[self.queue pushEvent:event];###注意这个event
[self dispatchEvent];
}
- (void)pushEvent:(TangramEvent *)event
{
if ([event isKindOfClass:[TangramEvent class]]) {
[self.queue addObject:event];####就是这个event
}
}
- (void)dispatchEvent
{
__weak typeof(self) wself = self;
dispatch_async(dispatch_get_main_queue(), ^{
__strong typeof(wself) sself = wself;
TangramEvent *event = [sself.queue popEvent];####还是这个event
while (event) {
[sself.dispatcher dispatchEvent:event];
event = [sself.queue popEvent];
}
});
}
从代码可以看出来,如果push操作是在子线程,那么就不会阻塞当前线程了,这么做便于并发.
这里和notifcationcenter的还有一个区别就是,
notficationcenter的发送消息,消息回调是同步执行的。 跟这里tangrmbus不一样