2020-01-01 tangrambus事件总线学习笔记

2020-01-01  本文已影响0人  我是小胡胡分胡

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不一样

上一篇下一篇

猜你喜欢

热点阅读