• New Android Injector with Dagger 2 — Part 3
  • Author of Mert şek
  • Translation from: The Gold Project
  • This article is permalink: github.com/xitu/gold-m…
  • Translator: woitaylor
  • Corresponding shengye102

Dagger New Android Injector: Dagger 2

If you haven’t read (1) and (2) yet, I suggest you read them first.

  • Dagger New Android Injector: Dagger 2 (1)
  • Dagger New Android Injector: Dagger 2

The profile

You can use DaggerActivity DaggerFragment, DaggerApplication to reduce the inside of the Activity/fragments/Application class template code.

Also, in the dagger Component, you can reduce the template code with AndroidInjector

.

DaggerAppCompatActivity and DaggerFragment

Remember to call the Androidinje.inject () method in a fragment or activity that uses the dagger. Similarly, if you want to use Injection in a fragment in the V4 package, you should have your activity implement the HasSupportFragmentInject interface and override the fragmentInjector method.

Recently, I moved this related code to BaseActivity and BaseFragment. Instead of declaring these in each activity, you put the common code in the base class.

So I was looking into the Dagger project and found that DaggerAppCompatActivity and DaggerFragment classes are just what I need. If Android likes inheritance, we can pretend to like inheritance 😛

Let’s take a look at what these classes do.

@Beta
public abstract class DaggerAppCompatActivity extends AppCompatActivity
    implements HasFragmentInjector, HasSupportFragmentInjector {

  @Inject DispatchingAndroidInjector<Fragment> supportFragmentInjector;
  @Inject DispatchingAndroidInjector<android.app.Fragment> frameworkFragmentInjector;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
  }

  @Override
  public AndroidInjector<Fragment> supportFragmentInjector() {
    return supportFragmentInjector;
  }

  @Override
  public AndroidInjector<android.app.Fragment> fragmentInjector() {
    returnframeworkFragmentInjector; }}Copy the code

As we can see from the above code, DaggerAppCompatActivity is not much different from the compatActivity we write ourselves, so we can make our Activity inherit DaggerAppCompatActivity to reduce the template code.

The DetailActivity class is as follows:

public class DetailActivity extends AppCompatActivity implements HasSupportFragmentInjector, DetailView {

    @Inject
    DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;

    @Inject
    DetailPresenter detailPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
    }

    @Override
    public void onDetailLoaded() {}

    @Override
    public AndroidInjector<Fragment> supportFragmentInjector() {
        returnfragmentDispatchingAndroidInjector; }}Copy the code

Let us DetailActivity inherit DaggerAppCompatActivity class, so that we don’t have to let DetailActivity class implements HasSupportFragmentInjector interface and overriding methods.

public class DetailActivity extends DaggerAppCompatActivity implements DetailView {

    @Inject
    DetailPresenter detailPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
    }

    @Override
    public void onDetailLoaded() {}}Copy the code

Now, isn’t that simpler.

DaggerApplication, AndroidInjector, AndroidSupportInjectionModule

See what else you can do to reduce template code. I’ve found that AndroidInjector helps simplify AppComponent. You can get information about this by reading the documentation for AndroidInjector.

Here is the code for the AppComponent class.

@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class,
        ActivityBuilder.class})
public interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance Builder application(Application application);
        AppComponent build();
    }

    void inject(AndroidSampleApp app);
}
Copy the code

The build() and seedInstance() methods have been defined in the AndroidInjector.Builder abstract class, So our Builder class can remove the Application () and build() methods from the above code by inheriting AndroidInje.Builder

.

Also, the AndroidInjector interface already has the inject() method. So we can remove the inject() method by inherits the AndroidInjector

interface (interfaces can inherit interfaces).

So our simplified AppComponent interface code looks like this:

@Component(modules = {
        AndroidSupportInjectionModule.class,
        AppModule.class,
        ActivityBuilder.class})
interface AppComponent extends AndroidInjector<AndroidSampleApp> {
    @Component.Builder
    abstract class Builder extends AndroidInjector.Builder<AndroidSampleApp> {}
}
Copy the code

Do you realize that our modules property has also changed? I was removed from the modules of the @ Component annotation attribute AndroidInjectionModule. Class and add the AndroidSupportInjectionModule. Class. This is because we are using fragments that support the library (v4 library). The AndroidInjectionModule is used to bind the Fragment of the app package to the dagger. . So if you want to in the v4 fragments used in injection, then you should be in your AppComponent adding AndroidSupportInjectionModule modules. The class.

We changed the way AppComponent is injected. So what does the Application class need to change?

As with DaggerActivity and DaggerFragment, we have the Application class inherit from the DaggerApplication class.

The previous code for the Application class looks like this:

public class AndroidSampleApp extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> activityDispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        DaggerAppComponent
                .builder()
                .application(this)
                .build()
                .inject(this);
    }

    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        returnactivityDispatchingAndroidInjector; }}Copy the code

The modified code is as follows:

public class AndroidSampleApp extends DaggerApplication {

    @Override
    protected AndroidInjector<? extends AndroidSampleApp> applicationInjector() {
        returnDaggerAppComponent.builder().create(this); }}Copy the code

The source code

You can get the modified source code from my GitHub. I didn’t merge this code into the main branch because I wanted to keep a history of the dagger usage in each branch. This will give readers an idea of how I’ve simplified the dagger usage step by step.

  • Demo

PS.

I’m not saying this is the most graceful practice of Dagger. This is just the way I use Dagger in my own projects. You can use this for your own projects if you like. Don’t do this if you really don’t want your Application class to inherit from a third party Application class (you can copy the DaggerApplication code into your own App class, Copy DaggerActivity/DaggerFragment inside the code to your own BaseActivity/BaseFragment, Use DaggerAppCompatActivity if you inherit AppCompatActivity. Whatever makes you happy. Finally, if you have better suggestions, please give me more advice.


Diggings translation project is a community for translating quality Internet technical articles from diggings English sharing articles. The content covers the fields of Android, iOS, front end, back end, blockchain, products, design, artificial intelligence and so on. For more high-quality translations, please keep paying attention to The Translation Project, official weibo and zhihu column.