注入Otto事件总线而不是使用静态单例的优点

时间:2015-07-16 19:15:07

标签: android dependency-injection dagger event-bus otto

在我的Android应用中,我使用Otto作为事件总线,Dagger用于依赖注入。

在Otto的用户指南和许多博客文章中,建议使用注入来获取总线单例。我已经做了一段时间,但最近我更加怀疑如果注入总线比使用简单的静态单例有任何优势。

使用注入我必须注入我希望能够在总线上发布UI事件的每个自​​定义View或ViewHolder。尤其是匕首,在我需要公共汽车的地方注入每个班级似乎有点笨拙。当然,我可以通过构造函数或setter方法传递总线,但是如果您考虑具有许多不同视图类型的适配器,那也可能有点笨拙。

我认为注入总线没有任何好处。在Otto的情况下,注入了一个具体的实现(Bus的一个实例)并且永远不会改变。由于订阅的工作方式,包装Otto进行去耦合没有任何意义,因为订阅有效。

那么,有没有人看到注入Otto的任何优点,我看不到?

1 个答案:

答案 0 :(得分:2)

在我看来,你应该把事件总线包装在你自己的类中,并使用依赖注入技术将它传递给客户端。

enter image description here

与仅通过调用静态getInstance()方法获取引用相比,此方法有几个优点:

  • 您的依赖关系变得明确。当您通过静态调用获取对象的引用时,依赖项隐藏在客户端的实现中,这使得代码易碎且难以理解。
  • 如果出现这种需要,将更容易切换到事件总线的不同实现。
  • 在测试中更容易模拟注入的依赖项
  • 依赖注入技术引入一定程度的斗争这一事实实际上是一件好事 - 如果你在挣扎,这往往表明你做错了什么。在你的情况下,我怀疑你是在滥用事件总线。

我说你有可能滥用事件总线,因为我真的不明白为什么你需要在View子类中引用它。我猜你发布有关用户与事件总线交互的通知,然后订阅ActivityFragment到事件总线以拦截这些事件。在这种情况下,事件总线是一个错误的工具(即使它工作得很好)。

在这种情况下事件总线是错误工具的原因是因为FragmentsActivity可以直接访问包含的View对象。您可以获取对这些Views的引用,并将FragmentsActivities注册为侦听器。不需要在这里解耦任何东西。

相反:考虑一个案例,你去重构你的Views,以便不再向事件总线发布任何内容(比如业务需求发生变化)。由于Views通知仅通过事件总线松散地耦合到包含FragmentActivity,因此您很可能忘记从Fragment中删除事件处理逻辑Activity,因此留下了“死代码”。这很快就会变得混乱。

更好的做法是使用观察者设计模式,让Views直接通知ActivitiesFragments,并且只有在处理涉及另一个组件时才能通过FragmentActivity;例如,另一个FragmentActivity)这些组件会将事件发布到事件总线。如果您遵循这种方法,您将需要在“顶级组件”中引用事件总线,并且不会涉及任何困难。

P.S。我最近发表了blog post which introduces some best practices for dependency injection in Android