-
Notifications
You must be signed in to change notification settings - Fork 847
Conversation
* one that takes an java.util.concurrent.Executor * one that takes a android.os.Handler.
…nder. This allows EventHandlerCreator to be varied, and touches fewer files.
Also add documentation and license.
Also added documentation and tidy.
Hi James, First of all, thanks for using and working on Otto. I'll tell you up front that as this pull request stands we won't be accepting it. Let me outline a few reasons why below...
The thread confinement as it exists now eliminates this. We intentionally enforce the Android main thread by default because that is what you should be using 99.9% of the time. This will actually keep your code clean because you always know on which thread the interaction will occur. As you mentioned, you can remove the thread confinement with the
Back to your implementation, you say that by making the poster determine threading it can lead to subtle bugs. Your implementation suffers the same problem but inverted. Here's an example: @Subscribe(MAIN) updateUi(UpdateEvent event) { /* do something */ }
@Subscribe(BG) updateFilesystem(UpdateEvent event) { /* do something */ } List<Users> users = userService.list();
UpdateEvent event = new UpdateEvent(users);
bus.post(users);
Collections.sort(users); In this example, my UI thread will get the ordering from the remote server whereas the filesystem callback gets a list sorted differently. These types of things are what Otto was designed to eliminate. The asynchronous nature of parts of this implementation also will now hold references to any objects posted for an unknown amount of time until the main thread dispatch can occur. If the object falls out of scope quickly, this prevents garbage collection. We advertise Otto as a replacement for the traditional manger/listener model where you register a listener who invokes methods on you when "interesting" things happen. These simple method calls very obviously happen on whatever thread the manager calls them on. We want Otto to behave this way so that the threading decisions and movements are on you, the very same as it would be if you were doing this manually. Additionally, as a user I think this API is too complicated which will likely lead to threading bugs due to lack of understanding of what each annotation option entails. The extreme simplicity of Otto's API and behavior is actually one of it's core features. It's intentionally a relatively "dumb" implementation so that you get zero unexpected behavior when using it. Now, what you have here isn't all bad despite everything I wrote. Before this I was already convinced that we needed a thread-moving bus implementation standardized. You can very easily write an extension of the bus which synchronously moves posts to an appropriate thread in about 20 lines of code. We'll likely include one in the next major version of the library. I encourage you to stay tuned for Otto 2.0's feature set. I think you'll find that it meets most of your requirements while still remaining extremely simple yet explicit. |
Hi Jake, Thanks for looking at my pull request. I realize that my implicit assumptions were that events were immutable, and that mutating events after dispatch would (certainly for me) feel a bit icky. Given enforcing immutability of an arbitrary object passed to you would be difficult at either compile time or runtime, this implementation of thread shifting would rely on those similar aesthetics. This convention is also expected by Scala Actors. I understand that one of the design tenets of Otto is extreme simplicity, and thread moving is not part of it. (I am resigned to the fact that you're not going to take my patch :(). However, developers are already trying to deliver messages to subscribers on different threads. We are encouraged to move functionality off the UI thread as much as possible. Relying on the caller/poster to post on the correct thread leads to a whole bunch of problems (for me):
Moving the threading decision to the subscriber is the important bit here. Putting an optional parameter on the annotation seemed like the least disgusting way of achieving this. If you are looking at thread moving for version 2.0, and I have any say in it, then I would very much prefer a subscriber/actor chooses. Let me know if I can do anything to help. |
We are undergoing discussions around this internally. It probably will end up like you wanted but with a bit less configuration and choice. Simplicity is an extremely high feature of Otto and we want to keep it that way. Are you using your version of Otto with these features you've implemented? I'm curious as to whether you use all of the threading options that you provided. |
I understand (and value) the desire to keep Otto simple. I'm currently using subscribers for:
I'm almost never using the default/ I quite like the string identifier idea put forward in #74, as I can see that there may be times when there may be a need for running lots of subscribers in a single-threaded context, but some of them are parallelisable. e.g. have database writes go in a single thread, and have another background thread. However:
If it helps you any with simplicity, other things I considered:
|
In many event buses, the event poster is responsible for deciding what thread the event will be delivered on. This often leads to confusion and subtle threading bugs. This confusion may be duplicated on every event post.
This patch adds an optional
thread
parameter to the Subscribe annotation. This lets the subscriber define what thread it needs to run in.It is backward compatible with noarg
@Subscribe
annotations. The annotations on the following two method signatures have identical semantics.This is a strawman implementation that defines four possible choices of threading that a subscriber can run on:
MAIN
- the UI thread,BACKGROUND
- a single background thread,ASYNC
- a thread from an unbounded thread pool andPOSTER_DECIDES
- the current behavior. This is the default.For best effect use
ThreadEnforcer.ANY
, so events can be posted from non-ui threads.This should solve previously closed issues #14 and #38 reasonably cleanly.