[英]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.