aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 880e3fdf7ecd940f4716c420a792d7c1ed689ff2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# EVENTBUS-KOTLIN

<img src="https://tokei.rs/b1/github/therealbush/eventbus-kotlin" alt="lines of code"/> <img src="https://img.shields.io/github/languages/code-size/therealbush/eventbus-kotlin" alt="code size"/> [![](https://jitpack.io/v/therealbush/eventbus-kotlin.svg)](https://jitpack.io/#therealbush/eventbus-kotlin) [![](https://jitpack.io/v/therealbush/eventbus-kotlin/month.svg)](https://jitpack.io/#therealbush/eventbus-kotlin)<br> 

*A simple, thread safe, and fast event dispatcher for Kotlin/JVM and Java.*

## Features

#### Simple to Use

Simple setup, and easy to learn, logical API

#### Thread Safe

Non locking event posting, and minimally locking registering/subscribing make this event dispatcher fit for use in
highly concurrent applications.

#### Fast

Because there is no reflection during event posting, and subscribers are cached after the first use of reflection, this
event dispatcher is much faster than other reflection based alternatives.

#### Flexible

This event dispatcher supports third party events, such as those used in MinecraftForge, and uses the Unsafe API to get
the value of a "cancelled" property at the same speed as direct access.

#### Parallel Event Posting

Listeners can be parallel, and they will be called on a Coroutine in the background. This is useful for heavy operations
that may slow down the posting thread.

## Usage

### Adding to your project:

If you have not already, add Jitpack as a repository:

```groovy
repositories {
    maven { url 'https://jitpack.io' }
}
```

Add the release of your choice in the dependencies block:

```groovy
dependencies {
    implementation 'com.github.therealbush:eventbus-kotlin:v1.0.1'
}
```

### Creating an EventBus:

`EventBus` can take a `Config` as an argument, however it is not required.

`Config` has four parameters. The following are the default arguments:

```kotlin
Config(
    logger = LogManager.getLogger("Eventbus"),
    parallelScope = CoroutineScope(Dispatchers.Default),
    thirdPartyCompatibility = true,
    annotationRequired = false
)
```

#### logger

The `Logger` this `EventBus` will use to log errors, or `EventBus#debug`

#### parallelScope

The `CoroutineScope` to use when posting events to parallel listeners. The default value will work just fine, but you
can specify a custom scope if desired.

[What is a Coroutine?](https://kotlinlang.org/docs/coroutines-overview.html)

#### thirdpartyCompatibility

Whether this `EventBus` should try to find a "cancelled" field in events being listened for that are not a subclass
of `Event`. This is experimental, and should be set to `false` if problems arise.

#### annotationRequired

Whether listeners need to be annotated with `@EventListener` to be subscribed to this
`EventBus`. This has no effect on anything else, and is just to improve code readability.

### Creating an Event:

Any class can be posted to an `EventBus`, but if you wish to use the base event class, extend `Event`, and implement the
property `cancellable`.

```kotlin
class SimpleEvent : Event() {
    override val cancellable = true
}
```

```java
public class SimpleEvent extends Event {
    @Override
    protected boolean getCancellable() {
        return false;
    }
}
```

### Creating a Listener:

Listeners are created by using the `listener` function:

```kotlin
listener<EventType>(priority = 0, parallel = false, receiveCancelled = false) {
    ...listener body ...
}
```

```java
listener(EventType.class, 0, false, false, event -> {
    ...listener body...
});
```

Listeners can be registered either directly with `EventBus#register`, or subscribed by returning them from a function or
property and subscribing the object they belong to with `EventBus#subscribe`.

The following are all valid. Listeners should be public, but they don't need to be.

```kotlin
val listener0 = listener<EventType> {
    ...listener body ...
}

val listener1 get() = listener<EventType> {
    ...listener body ...
}

fun listener2() = listener<EventType> {
    ...listener body ...
}
```

```java
public Listener listener0 = listener(EventType.class, event -> {
    ...listener body...
});

public Listener listener1() {
    return listener(EventType.class, event -> {
        ...listener body...
    });
}
```

#### priority

The priority of this `Listener`. Listeners with a higher priority will receive events before listeners with a lower
priority.

#### parallel

Whether this `Listener` should be called on the thread that called `EventBus#post`, or on the
`CoroutineScope` in `Config#parallelScope`. `EventBus#post` will not wait for parallel listeners to complete.

*Currently, there is no way to get a reference to the `Job` created by `launch` when posting to parallel listeners, and
listeners are not `suspend` lambdas. This may change in the future.*

#### receiveCancelled

Whether this `Listener` should receive events that have been cancelled. This will work on third party events
if `Config#thirdPartyCompatibility` is enabled.

### Subscribing an Object:

Calling `EventBus#subscribe` and `EventBus#unsubscribe` with an object will add and remove listeners belonging to that
object from the EventBus. Only listeners in subscribed objects will receive events.

Companion objects and singleton object classes can be subscribed, but subscribing a KClass will not work.

### Posting an Event:

Calling `EventBus#post` will post an event to every listener with an **exactly** matching event type. For example, if
event B extends event A, and event A is posted, B listeners will not receive it.

Events are **not** queued: only listeners currently subscribed will be called.

`EventBus#post` will return true if the posted event is cancelled after posting it to sequential listeners. Event cancel
state is checked once before posting to parallel listeners, because order is not guaranteed.

### Still Confused?

Read [this](https://github.com/therealbush/eventbus-kotlin/tree/master/src/test) for usage examples.