56

我正在评估Android应用程序的依赖注入(DI)框架。顶级竞争者是:匕首(带黄油刀)和Android注释。据我所知,匕首和黄油刀来自相同的来源广场,它们相辅相成。我这里还有是我要找的关键矩阵:匕首和黄油刀与Android注释

  1. 易于使用(我们的构建是基于摇篮,我们使用Android Studio IDE中)
  2. 测试支持(我们使用Robotium进行功能测试和RoboLectric单元测试)
  3. 性能(DI框架使用反射,哪一个是更快?)
+4

谷歌特别要求不要使用依赖注入https://developer.android.com/training/articles/memory.html#Android –

+7

@IllegalArgument链接只是说“这些框架往往要做大量的初始化过程来扫描注释”。 Dagger和AndroidAnnotations(可能也是Butter Knife,因为它声称,但我不确定)都在编译时做了他们的魔法,可能不适用。 – kizzx2

+0

请参阅http://www.reddit.com/r/androiddev/comments/28vlrt/dagger_and_butter_knife_vs_android_annotations/ – ChrLipp

回答

5

谷歌不问具体是不使用依赖注入。但通过阅读那里的请求,他们将更多地讨论基于guice/reflection的DI库。诸如android注释之类的东西不使用反射,并且完全编译时间生成的代码,而黄油刀和匕首使用针对android优化的少量反射。但据说稍微比android注释更强大。这真的取决于该项目以及您愿意承担多少性能。在我看来,使用黄油刀很大程度上可以加速代码的开发。如果你需要更多的使用android注释。最后如果你愿意采取轻微的表现,由于反射最好的选择,而不会绝对破坏性能与强大的基于guice的反射是匕首+黄油刀。

+7

Google正在联合开发dagger2:http://google.github.io/dagger/ –

+1

他们自己做了自己的,这就是为什么:https://developer.android.com/tools/data-binding/guide.html https://www.youtube.com/watch?v = 5sCQjeGoE7M –

49

AndroidAnnotations
使用了编译时间注释处理。它生成一个带有下划线的子类,该子类用于原始名称(从MyActivity生成的MyActivity_)。所以为了让它工作,你必须使用生成的类来引用,而不是原来的类。

它具有非常丰富的功能集,请参阅list of available annotations

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)和一些事件绑定(对于一个完整列表,请参阅命名空间目录here,只需计算OnXXX事件注释)。

Dagger
是Android一个DI实现,类似于吉斯。它还使用编译时注释处理并生成用于手动注入的对象图。您可以区分应用程序对象图和范围对象图,以便注入(例如)在活动中。这里你可以看到一个Application.onCreate例如:

@Override public void onCreate() { 
    super.onCreate(); 
    objectGraph = ObjectGraph.create(getModules().toArray()); 
    objectGraph.inject(this); 
    // use injected classes 
} 

我发现这是很难下手的匕首,但是这可能只是我的经验。但看到一些视频在这里美好的开始:12

从视功能集点我想说的是匕首实现这可以被比作AndroidAnnotation的@EBean@Bean功能功能。

摘要
如果你是比较容易使用,测试支持和性能我无法找到使用AndroidAnnotation和ButterKnife +匕首太大的区别。编程模型中存在差异(使用_而不是使用原始类型并手动调用注入),并在特征集中使用差异。

AndroidAnnotation为您提供了完整的功能列表,但将您与某些图书馆联系起来。例如,如果你使用它的休息API,你必须使用Spring的Android。无论您是否使用OrmLite,您还可以使用OrmLite(@OrmLiteDao)等功能的注释。

最后,这是一个味道的问题,至少在我看来。

+0

我认为你对ButterKnife犯了一个错误:它使用编译时注释(RetentionPolicy.CLASS),但它在运行时注入代码,导致更多的时间。 – ech0s7r

+3

我认为所有的解决方案都会在编译期间生成代码,并且调用此代码(在运行时)执行注入。例如,在Android Annotations中,它会生成一个为MyActivity执行注入的子类(MyActivity_')。在Butterknife中,你必须称之为“黄油刀”。注入(this)'代表生成的代码。 – ChrLipp

+0

不喜欢Android自己的数据绑定库吗? https://developer.android.com/tools/data-binding/guide.html 你最终会忘记所有这些。 –

19

这是尼斯文章Dzone blog

我们需要比较各的功能,如:需要

  • 最小罐
  • ActionBarSherlock兼容性
  • 注射液点击听众
  • POJO注入
  • 性能

enter image description here

只有pojo注射在butterknife失踪!所以看起来像Butterknife是赢家!

Source

+1

我会考虑添加到这个图表的另一行是Butterknife不支持的“支持库项目”,但AndroidAnnotations通过resName属性完成(请参阅https://github.com/excilys/androidannotations/wiki/Library-projects) 。这对我使用Butterknife来说是一个破坏者。 –

+0

-1:这个问题不是关于[RoboGuice](https://github.com/roboguice/roboguice)(无论如何已经退役并且不再维护),而是关于[AndroidAnnotations](http://androidannotations.org ) – TmTron

0

我认为的好(在性能方面)ButterKnife和AndroidAnnotation是第二。 ButterKnife使用编译时注解(RetentionPolicy.CLASS),但它在运行时注入代码,导致更多的时间。相反,AndroidAnnotations在编译时处理所有注释。

+3

“ButterKnife在运行时注入代码” - 你确定吗? – naXa

+0

阅读本文的第一段http://www.thekeyconsultant.com/2013/09/5-reasons-you-should-use-butterknife.html – Redman

1

reddit-thread通过@ChrLipp提到了有人使用所有这三个在同一项目上谁,讲匕首+ butterknife的高度,但也给AndroidAnnotations它的地方:

对于依赖注入,butterknife用于视图,匕首是 用于所有对象,并强烈建议和Android注释 创建更多的框架,而不是 开发Android而不是 注入对象到您的类,因此每个库是相当不同的 彼此不同。匕首相当于Guice,但速度要快得多 。匕首更强大,然后ButterKnife和Android 注释,因为它注入的所有对象,而不是ButterKnife和Android注释只注入一组对象。

匕首可能是一个痛苦的设置和配置,但是非常值得它一旦 你完成了。但是再次,因为这些都是相互不同的 ,这一切都取决于你需要什么 该项目。

另外,如果你真的想要,在你的项目中你可以使用ButterKnife,Android Annotations和Dagger全部在相同的 项目中。他们每个人都有相同的想法,但做一些不同的事情,所以你可以使用它们。

3

使用Android Annotations或Butterknife来简化您的编码。但不要去Roboguice! Roboguice强制你的活动,片段扩展到roboguice类。一点都不好玩!

+0

从RoboActivity(从Activity扩展而来)扩展时存在什么问题可以从Activity延伸?你在这里没有失去任何东西。 – vijay

5

你应该Toothpick给予一试。

牙签是(每自述):

  • 纯java
  • 快,它不使用反射而是注释处理
  • 简单,灵活,可扩展的&强大,鲁棒&测试
  • 线程安全
  • 记录&开源代码
  • 范围安全:它强制无泄漏应用
  • 测试导向:它使测试更容易
  • 它工作得很好,Android或任何其他基于上下文的框架(如Web容器)

它甚至可以在大多数情况下比Dagger 2更快,而且更简单。

注:是的,我是其中一位作者。

1

为什么要打扰依赖注入?

之前还有人会问 - “但是我为什么还要考虑DI?人们说代码更干净,但是我的代码从不混乱。“现在,当你回顾你前几天写的一个小型业余爱好项目时,你可能没有做任何复杂的事情,这可能是真的,跳过单元测试,等等。但现实是不同的。通过使用依赖注入可以获得很多东西,其中一些比其他更明显。

enter image description here See full comparison of All Android Dependency Injection libraries

可测

这一次大概是从我的角度来看,最重要的一个。每当你编写单元测试时(你应该一直在写它们),你需要确保你正在测试你自己的代码,并且只针对有问题的类。您不想依赖于某些库或另一个单独测试的类的逻辑。你怎么做到这一点?最好的方法是使用注入而不是实际实现的mock。毕竟,您不希望与外部第三方服务对话的课程的测试依赖于互联网连接以及您所收取的真实凭证。

代码和责任分离

基于我所提到的有关测试,它变得清晰,代码分离会自然发生。这将允许您将代码拆分为一次负责一件事的较小块。较小的代码块导致清洁,清洁导致可读性,可读性导致更少的错误。通过这一切,我们提高了代码的可维护性。

可替换性和适应

重构是任何开发项目的一个自然组成部分。我们将开发未来需要修改的代码,甚至完全替代某些实现。我们要做的越少 - 越好。在依赖注入的帮助下,您可以更轻松地调整代码,引入新的依赖关系,甚至完全更改它们。