[英]Is “inject everything” a bad practice in Android?
关于依赖注入的研究我发现一些方法建议注入所有东西,而另一些方法则说没有必要这样做 。
在我目前的项目中,关于依赖注入的经验法则是“ 如果该类是由我创建的,那么我可以将其注入 ”。 换句话说,只有像SimpleDateFormat
, ArrayList
, HashMap
这样的类才是我项目中的新功能。 我做这种方法的意图是,一旦在Activity
调用Injector.getApplicationComponent().inject(this)
,我就可以@Inject
任何类。 基本上我的所有类都有一个带@Inject
的非args构造函数。
我主要使用DI,因为我认为一旦new
运算符由Dagger生成的类专门使用,它将改善性能和内存使用。 但我读了Dagger 1开发人员的帖子 ,说DI对性能没有影响,用法基本上是为了减少样板。
第一个问题是:
我的项目运行没有问题,我认为“注入一切”的方法有助于更好地组织,尽管有一些缺点。
使用此方法的一个示例是以下类:
public class TimelineEntryAdapter {
@Inject
Provider<TwitterEntry> mTwitterProvider;
@Inject
Provider<InstagramEntry> mInstagramProvider;
@Inject
Provider<FacebookEntry> mFacebookProvider;
@Inject
TimelineEntryComparator mComparator;
@Inject
public TimelineEntryAdapter() {
}
第二个问题是:
如果第二个问题的答案是“否”,那么有一种更好的方法来处理非args构造函数来创建类吗? 因为当我用@Inject
注释创建一个非args构造函数并且一个类需要一些参数来处理时,我必须使用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;
}
一旦所有参数在流程中同时获得,所有参数都可以在构造函数上设置。
关于依赖注入的研究我发现一些方法建议注入所有东西,而另一些方法则说没有必要这样做。
您引用的froger_mcs博客条目并不主张注入所有内容。 它非常明确地指出:
这篇文章的目的是展示我们可以做什么,而不是我们应该做什么。
它继续说明注入一切的缺点:
如果您想在项目中使用Dagger 2几乎所有内容,您很快就会看到生成的代码用于注入的64k方法计数限制。
现在,问你的问题:
Dagger 2在Android应用程序中没有任何性能优势?
虽然Dagger 2提供了优于其他基于反射的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<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;
}
考虑总是宣布课程的范围。 是单身人士吗? 它可以重复使用吗? 一旦应用程序变得复杂和庞大,这个小细节可以拯救您。
使用init方法声明所有注入变量的优点是具有干净的代码,易于维护,因为所有注入的都在这一个位置。 但这实际上是偏好:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.