Is "injecting everything" bad practice in Android?

While researching injecting addiction, I found several approaches that suggest injecting all and others saying that it shouldn't be done .

In my current project, my rule of thumb regarding Dependency Injection is "if the class was created by me, I make it injectable". In other words, only the classes, such as SimpleDateFormat

, ArrayList

, HashMap

, are new in my project. My intention to make this approach is that I can @Inject

any class ever calling Injector.getApplicationComponent().inject(this)

in Activity

. Basically all of my classes have a no-argument constructor with @Inject

.

I was primary using DI because I thought it would improve performance and memory usage once the statement new

was used exclusively by Dagger generated classes. But I read a post from Dagger developer 1 saying that DI has no performance impact and usage is basically flattening the pattern.

First question:

  • Dagger 2 lacks performance benefits in Android app?

My project runs smoothly, and I think the "put everything" approach helps to better organize, despite some drawbacks.

An example of using this approach is the following class:

public class TimelineEntryAdapter {

@Inject
Provider<TwitterEntry> mTwitterProvider;

@Inject
Provider<InstagramEntry> mInstagramProvider;

@Inject
Provider<FacebookEntry> mFacebookProvider;

@Inject
TimelineEntryComparator mComparator;

@Inject
public TimelineEntryAdapter() {
}

      

Second question:

  • Are you applying everything wrong on Android?

If the answer to the second question is "No", is there a better way to handle the non-args constructor to create classes? Because when I create an annotated non-args constructor @Inject

and the class needs some parameters to work, I have to use 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;
}

      

All parameters can be set in the constructor as soon as all are received at the same time in the stream.

+3


source to share


2 answers


While researching the question of dependency injection, I found several approaches that suggest injecting all and others, saying that it is optional.

The froger_mcs blog post you cite does not protect all injections. It says quite clearly:

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

And then it says about the lack of injection of everything:

If you want to use Dagger 2 for almost anything in your project, you will quickly see that most of the 64k label limit is used by the generated injection code.

Now, to your questions:

Dagger 2 lacks performance benefits in Android app?

While Dagger 2 offers a performance advantage over other reflection-based DI structures (such as Guice), it does not claim to offer any performance advantage over manually plotting objects by calling constructors. You can check the generated classes yourself to make sure they actually still call the constructors.



Is it really bad practice to implement everything in Android?

Ok, take the following very common Android code:

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

      

Should we extract IntentFactory

and inject this with dagger 2 to avoid the keyword new

here? At this point, it is easy to approach pedantry. The advice in the other answer you quoted about the difference between injectable and new elements is more flexible and elegant.

Let's move on to the next question:

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

Using setters is the wrong approach for parameters. You must differentiate between dependencies and parameters. Dependencies usually have the same lifecycle as the object itself. During the life of an object, the methods exposed for that object can be called with different parameters.

+6


source


I'm not a professional in dependency management, but I use it in my company, so here's how I see it.

Typing is all basically good. I do everything that is used somewhere else (other modules, classes, packages), and also only static things (static classes with a hidden constructor), things that are only used internally.

What's the advantage of this? Well the dependency system will take care of getting the instance and discarding it. It will automatically clear itself. Also, using scopes in classes will allow you to create a class that always only has one instance in the entire application (multiple threads accessing it) or make it reusable (each thread it needs gets its own instance).

Also I think you could clean up your classes like this:



@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;
}

      

Consider always declaring class scope. Is this Singleton? Will it be reused? This little detail can save you once the application gets complex and large.

The advantage of using the init method to declare all the entered variables is to have clean code that is easy to maintain, since all of the entered value is in that place. But this is really a preference :)

+3


source







All Articles