匕首和黄油刀与Android注释
我正在评估Android应用程序的dependency injection(DI)框架。 顶级竞争者是:匕首(与黄油刀)和Android注释。 我明白,匕首和黄油刀来自相同的来源广场,它们是相辅相成的。 这里是我正在寻找的关键matrix:
- 易于使用(我们的构build基于Gradle,我们使用Android Studio IDE)
- testing支持(我们使用Robotium进行functiontesting,使用RoboLectric进行unit testing)
- 性能(DI框架使用reflection,哪个更快?)
AndroidAnnotations
使用编译时注释处理。 它会生成一个带有下划线的子类,该子类被添加到原始名称(由MyActivity_
生成的MyActivity
)中。 所以为了使它工作,你总是必须使用生成的类来引用,而不是原来的类。
它具有非常丰富的function集,请参阅可用注释列表 。
牛油刀
也使用编译时间注释处理,但是它产生由中心类( ButterKnife
)使用的查找器类。 这意味着您可以使用原始类进行引用,但必须手动调用注入。 来自ButterKnife的复制介绍:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.inject(this); // TODO Use "injected" views... }
ButterKnife支持视图注入(AndroidAnnotations相当于@ViewById
和@ViewsById
)和一些事件绑定(对于完整列表,请参阅这里的命名空间目录,只需计算OnXXX
事件注释)。
匕首
是Android的DI实现,类似于Guice。 它还使用编译时注释处理并生成用于手动注入的对象图。 您可以区分应用程序对象图和范围对象图,以便在活动中注入。 在这里你可以看到一个Application.onCreate
例子:
@Override public void onCreate() { super.onCreate(); objectGraph = ObjectGraph.create(getModules().toArray()); objectGraph.inject(this); // use injected classes }
我发现从匕首开始很难,但这可能只是我的经验。 不过请参阅这里的一些video以获得更好的开始: 1,2
从function设置的angular度来看,我会说Dagger实现了可以与AndroidAnnotation的@EBean
和@Bean
function进行比较的function。
概要
如果您正在比较易用性,testing支持和性能,我无法find使用AndroidAnnotation和ButterKnife + Dagger的区别。 编程模型中的差异(使用_
而不是使用原始模型的类并手动调用注入)和特征集中。
AndroidAnnotation为您提供了一个完整的function列表,但将您与某些库关联起来。 例如,如果你使用它的restAPI,你必须使用Spring的Android。 无论您是否使用OrmLite,您也可以使用OrmLite( @OrmLiteDao
)等function的注释。
最后,至less在我看来,这是一个品味的问题。
这是Dzone博客中的好文章。
我们需要比较每个的特点,比如:
- 最低瓶子要求
- ActionBarSherlock兼容性
- 注入点击听众
- POJO注射
- 性能
只有Pojo注射失败在butterknife! 所以看起来Butterknife是赢家!
资源
Google确实要求不要使用dependency injection。 但是通过阅读这些请求,他们可以更多地讨论基于guice /reflection的DI库。 诸如android注解之类的东西不使用reflection和完全编译时间生成的代码,而黄油刀和匕首则使用针对android优化的less量reflection。 但据说稍稍比android注释更强大。 这真的取决于这个项目,以及你愿意承担多less的业绩。 在我看来,使用黄油刀是很多加速自己的代码开发。 如果你需要更多的使用android注释。 最后如果你愿意采取一个轻微的performance,由于reflection最好的select,而不是绝对破坏性能与强大的基于guicereflection是匕首+黄油刀。
你应该试试牙签 。
牙签是(根据自述文件):
- 纯java
- 快,它不使用reflection而是注释处理
- 简单,灵活,可扩展和function强大,强大和testing
- 线程安全
- logging和开源
- 范围安全:它强制实施无泄露应用程序
- 面向testing:它使testing更容易
- 它适用于Android或任何其他基于上下文的框架(如Web容器)
它在大多数情况下甚至比Dagger 2更快,而且更简单。
注:是的,我是其中一位作者。
使用Android Annotations或Butterknife来简化您的编码。 但是不要去Roboguice! Roboguice强制你的活动,片段扩展到roboguice类。 一点都不好玩!
看起来像谷歌select匕首,因为他们正在与创造它的广场联合开发 。
关于Butterknife和Dagger本身,SO的问题在Dagger -and-butterknife-android之间有所区别 ,从而阐明了它们是如何相互补充的。
@ChrLipp提到的reddit-thread有一个人在同一个项目中使用了三个 ,高度评价了匕首+黄油刀,同时也给出了AndroidAnnotations的地方:
对于dependency injection来说,butterknife用于Views,Dagger用于所有对象,强烈推荐,Android Annotations创build更多的框架来开发Android,而不是注入对象到你的类中,因此每个库都是相当不同的。 匕首相当于Guice,但要快得多。 Dagger比ButterKnife和Android Annotations更强大,因为它注入所有对象,而不是ButterKnife和Android Annotations,它们只注入一组对象。
匕首可能是一个痛苦的设置和configuration,但一旦你完成它是非常值得的。 但是,再次,因为这些都是彼此不同的,这一切都取决于你的需求是什么样的项目。
另外,如果你真的想要的话,你可以在同一个项目中使用ButterKnife,Android Annotations和Dagger。 他们每个人都有相同的想法,但做一些不同的东西,所以你可以使用它们。
最终,如果你使用三者之一,你将很难转换到Android的数据绑定。 如果您需要考虑性能,这是最快的:
我认为(性能方面)ButterKnife和AndroidAnnotation之间的差距更大。 ButterKnife使用编译时注解(RetentionPolicy.CLASS),但它在运行时注入代码,导致更多的时间。 相反,AndroidAnnotations,在编译时处理所有注释。
为什么要打扰dependency injection?
之前还有人会问 – “但为什么我还要考虑DI? 人们说代码更干净,但是我的代码从来没有混乱过。“现在,当你回顾你前几天写的一个小型的业余爱好项目时,你可能不会做任何复杂的事情,这可能是真的,跳过unit testing,等等。 但现实是不同的。 使用dependency injection有很多东西,有些比其他的更明显。
查看所有Androiddependency injection库的完整比较
可测性
这个可能是我认为最重要的一个。 每当你正在编写unit testing时(你应该一直在写它们),你需要确保你正在testing你自己的代码,并且只能针对有问题的类。 你不想依赖于一些图书馆或另一个单独testing的类的逻辑。 你怎么做到这一点? 最好的方法是使用注入而不是真正的实现模拟。 毕竟,您不希望与外部第三方服务对话的课程的testing依赖于互联网连接和您正在收取的真实凭证。
代码和责任分离
基于我提到的testing,很明显,代码分离将自然发生。 这将允许您将代码拆分成一次负责一件事的较小块。 代码更小的块导致清洁,清洁导致可读性,可读性导致更less的错误。 通过这一切,我们提高了代码的可维护性。
可更换性和适应性
重构是任何开发项目的自然部分。 我们将开发将来需要修改的代码,甚至完全替代一些实现。 我们要做的越less越好。 在dependency injection的帮助下,您可以更轻松地调整代码,引入新的依赖关系,甚至完全更改它们。