"inject everything" 在 Android 中是一种不好的做法吗?

Is "inject everything" a bad practice in Android?

在研究依赖注入时,我发现了一些建议inject everything and other saying that 的方法。

在我当前的项目中,我关于依赖注入的经验法则是“如果 class 是我创建的,我将其设置为可注入的 ”。换句话说,只有 class 像 SimpleDateFormatArrayListHashMap 是我项目中的新项目。我采用这种方法的意图是,一旦在 Activity 中调用 Injector.getApplicationComponent().inject(this),我就可以 @Inject 任何 class。基本上我所有的 classes 都有一个带 @Inject.

的非参数构造函数

我主要使用 DI,因为我认为一旦 Dagger 生成的 classes 专门使用 new 运算符,它会提高性能和内存使用。但是我从 Dagger 1 开发者那里读到 post 说 DI 对性能没有影响,使用基本上是为了减少样板。

第一个问题是:

我的项目 运行 没有问题,我认为 "inject everything" 的方法有助于更好地组织,尽管存在一些缺点。

使用此方法的示例如下 class:

public class TimelineEntryAdapter {

@Inject
Provider<TwitterEntry> mTwitterProvider;

@Inject
Provider<InstagramEntry> mInstagramProvider;

@Inject
Provider<FacebookEntry> mFacebookProvider;

@Inject
TimelineEntryComparator mComparator;

@Inject
public TimelineEntryAdapter() {
}

第二个问题是:

如果第二个问题的答案是"No",有没有更好的方法处理non-args构造函数来创建classes?因为当我创建带有 @Inject 注释的非参数构造函数并且 class 需要一些参数时,我必须使用 setters:

public class SavelArtist {

private MusicBrainzArtist mMusicBrainzArtist;

private DiscogsArtist mDiscogsArtist;

private List<SavelTweet> mTweetList;

private SpotifyArtist mSpotifyArtist;

private List<SavelInstagram> mInstaTimeline;

private List<SavelFacebook> mFacebookTimeline;

private List<SavelRelease> mReleases;

@Inject
Provider<SavelRelease> mReleaseProvider;

@Inject
public SavelArtist() {
}

public void setMusicBrainzArtist(MusicBrainzArtist mbArtist) {
    mMusicBrainzArtist = mbArtist;
}

public void setDiscogsArtist(DiscogsArtist discogsArtist) {
    mDiscogsArtist = discogsArtist;
}

public void setTweetList(List<SavelTweet> tweetList) {
    mTweetList = tweetList;
}

public void setSpotifyArtist(SpotifyArtist spotifyArtist) {
    mSpotifyArtist = spotifyArtist;
}

public void setInstaTimeline(List<SavelInstagram> instaTimeline) {
    mInstaTimeline = instaTimeline;
}

public void setFacebookTimeline(List<SavelFacebook> fbTimeline) {
    mFacebookTimeline = fbTimeline;
}

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

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

注入基本就OK了。我让其他地方使用的所有东西(其他模块,classes,包)都可以注入,只有静态的东西(带有隐藏构造函数的静态classes),只能在内部使用的东西不可注入。

它有什么好处? 那么依赖系统将负责获取实例并丢弃它。它会自动清理。此外,在 classes 上使用范围将使您能够创建一个 class,它在整个应用程序中始终只有一个实例(多个线程访问它)或使其可重用(每个需要它的线程都会得到一个自己的实例)。

此外,我认为您可以像这样清理 classes:

@Reusable (Maybe a good Idea?)
public class SavelArtist {

private MusicBrainzArtist mMusicBrainzArtist;

private DiscogsArtist mDiscogsArtist;

private List<SavelTweet> mTweetList;

private SpotifyArtist mSpotifyArtist;

private List<SavelInstagram> mInstaTimeline;

private List<SavelFacebook> mFacebookTimeline;

private List<SavelRelease> mReleases;

private Provider<SavelRelease> mReleaseProvider;

public SavelArtist() {
}

@Inject
public void init(Provider<SavelRelease> mReleaseProvider) {
  this.mReleaseProvider = mReleaseProvider;
}

考虑始终声明 class 的范围。是单例吗?它可以重复使用吗?一旦应用程序变得复杂和庞大,这个小细节可以拯救您。

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

Studying about dependency injection I found some approaches that suggests to inject everything and other saying that it's not necessary to do so.

你引用的froger_mcs blog entry并不提倡注入一切。它非常清楚地指出:

The purpose of this post is to show what we can do, not what we should do.

它继续说明注入所有内容的缺点:

If you want to use Dagger 2 for almost everything in your project you will quickly see that big piece of 64k methods count limit is used by generated code for injections.

现在,回答您的问题:

Dagger 2 does not any performance advantage in Android application?

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

Is it a bad practice to inject everything in Android?

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

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

我们是否应该提取一个 IntentFactory 并使用 Dagger 2 注入它只是为了避免此处的 new 关键字?在这一点上,很容易接近迂腐。 中关于注射剂和新剂的区别的建议更加灵活和优雅。

继续你的下一个问题:

If the answer for the second question is "No", there is a better way to handle the non-args constructor to create classes? Because when I create an non-args constructor with @Inject annotation and a class need some parameters to work with, I must use setters:

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