在Android中“注入一切”是一种不好的做法吗?

关于dependency injection的研究我发现一些方法建议注入所有东西,而另一些方法则说没有必要这样做 。

在我目前的项目中,关于dependency injection的经验法则是“ 如果该类是由我创建的,那么我可以将其注入 ”。 换句话说,只有像SimpleDateFormatArrayListHashMap这样的类才是我项目中的新function。 我做这种方法的意图是,一旦在Activity调用Injector.getApplicationComponent().inject(this) ,我就可以@Inject任何类。 基本上我的所有类都有一个带@Inject的非args构造函数。

我主要使用DI,因为我认为一旦new运算符由Dagger生成的类专门使用,它将改善性能和内存使用。 但我读了Dagger 1开发人员的post ,说DI对性能没有影响,用法基本上是为了减少样板。

第一个问题是:

  • Dagger 2在Android应用程序中没有任何性能优势?

我的项目运行没有问题,我认为“注入一切”的方法有助于更好地组织,尽管存在一些缺点。

使用此方法的一个示例是以下类:

 public class TimelineEntryAdapter { @Inject Provider mTwitterProvider; @Inject Provider mInstagramProvider; @Inject Provider mFacebookProvider; @Inject TimelineEntryComparator mComparator; @Inject public TimelineEntryAdapter() { } 

第二个问题是:

  • 在Android中注入所有东西是不好的做法?

如果第二个问题的答案是“否”,那么有一种更好的方法来处理非args构造函数来创建类? 因为当我用@Inject注释创建一个非args构造函数并且一个类需要一些参数来处理时,我必须使用setters

 public class SavelArtist { private MusicBrainzArtist mMusicBrainzArtist; private DiscogsArtist mDiscogsArtist; private List mTweetList; private SpotifyArtist mSpotifyArtist; private List mInstaTimeline; private List mFacebookTimeline; private List mReleases; @Inject Provider mReleaseProvider; @Inject public SavelArtist() { } public void setMusicBrainzArtist(MusicBrainzArtist mbArtist) { mMusicBrainzArtist = mbArtist; } public void setDiscogsArtist(DiscogsArtist discogsArtist) { mDiscogsArtist = discogsArtist; } public void setTweetList(List tweetList) { mTweetList = tweetList; } public void setSpotifyArtist(SpotifyArtist spotifyArtist) { mSpotifyArtist = spotifyArtist; } public void setInstaTimeline(List instaTimeline) { mInstaTimeline = instaTimeline; } public void setFacebookTimeline(List fbTimeline) { mFacebookTimeline = fbTimeline; } 

一旦所有参数在流程中同时获得,所有参数都可以在构造函数上设置。

关于dependency injection的研究我发现一些方法建议注入所有东西,而另一些方法则说没有必要这样做。

您引用的froger_mcs博客条目并不主张注入所有内容。 它非常明确地指出:

这篇文章的目的是展示我们可以做什么,而不是我们该做什么。

它继续说明注入一切的缺点:

如果你想在项目的几乎所有东西中使用Dagger 2,你很快就会看到生成的代码用于注入的64k方法计数限制。

现在,问你的问题:

Dagger 2在Android应用程序中没有任何性能优势?

虽然Dagger 2提供了优于其他基于reflection的DI框架(例如Guice)的性能优势,但它并不声称通过调用构造函数来手动构建对象图提供任何性能优势。 您可以自己检查生成的类,看看它们最终仍然会调用构造函数。

在Android中注入所有东西是不好的做法?

好吧,让我们采取以下非常常见的Android代码:

 Intent nextActivity = new Intent(this, NextActivity.class); startActivity(nextActivity); 

我们应该提取一个IntentFactory并使用Dagger 2注入它只是为了避免使用new关键字吗? 在这一点上,很容易接近迂腐。 您引用的另一个答案中关于注射剂和新产品之间差异的建议更灵活,更优雅。

继续你的下一个问题:

如果第二个问题的答案是“否”,那么有一种更好的方法来处理非args构造函数来创建类? 因为当我用@Inject注释创建一个非args构造函数并且一个类需要一些参数来处理时,我必须使用setter:

使用setter是参数的错误方法。 您应该区分依赖项参数 。 依赖关系通常与对象本身具有相同的生命周期。 在对象的生命周期中,可以使用不同的参数调用为该对象公开的方法。

我不是依赖管理的专业人士,但我在公司使用它,所以这就是我看到它的方式。

注入一切基本上都很好。 我将在其他地方使用的所有内容(其他模块,类,包)可注入,并且只使用静态内容(具有隐藏构造函数的静态类),仅在内部使用不可注入的内容。

它的优点是什么? 好依赖系统将负责获取实例并丢弃它。 它会自动清理。 同样在类上使用作用域将使您能够创建一个在整个应用程序中始终只有一个实例的类(多个线程访问它)或使其可重用(需要它的每个线程都是一个自己的实例)。

另外我认为你可以像这样清理你的课程:

 @Reusable (Maybe a good Idea?) public class SavelArtist { private MusicBrainzArtist mMusicBrainzArtist; private DiscogsArtist mDiscogsArtist; private List mTweetList; private SpotifyArtist mSpotifyArtist; private List mInstaTimeline; private List mFacebookTimeline; private List mReleases; private Provider mReleaseProvider; public SavelArtist() { } @Inject public void init(Provider mReleaseProvider) { this.mReleaseProvider = mReleaseProvider; } 

考虑总是宣布课程的范围。 这是单身人士吗? 它可以重复使用吗? 一旦应用程序变得复杂和庞大,这个小细节可以拯救您。

使用方法init声明所有注入变量的优点是具有干净的代码,易于维护,因为所有注入的都在这一个位置。 但这实际上是偏好:)