[译] 全新 Android 注入器 : Dagger 2(三)

全新 Android 注入器 : Dagger 2(三)

若是你尚未阅读(一)和(二),我建议你先阅读它们。html

概要

你可使用 DaggerActivityDaggerFragmentDaggerApplication 来减小 Activity/Fragment/Application 类里面的模板代码。前端

一样的,在 daggercomponent 中,你也能够经过 AndroidInjector<T> 去减小模板代码。android

DaggerAppCompatActivity and DaggerFragment

在使用 daggerfragment 或者 activity 中要记得调用 AndroidInjection.inject() 方法。 一样的,若是你想要在 v4 包里面的 fragment 中使用 Injection,你应该让你的 activity 实现 HasSupportFragmentInject 接口而且重写 fragmentInjector 方法。ios

最近,我把这些相关代码移到 BaseActivityBaseFragment。由于与其在每一个 activity 中声明这些,还不如把共同的代码放到基类里面。git

因而我在研究 dagger 项目的时候发现 DaggerAppCompatActivityDaggerFragment 这些类正好是我所须要的。若是说 Android 喜欢继承,那么咱们也能够伪装喜欢继承 😛github

让咱们看看这些类作了些神马。后端

@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() {
    return frameworkFragmentInjector;
  }
}
复制代码

从上面的代码能够看出 DaggerAppCompatActivity 跟咱们本身写的 Activity 并无多大的区别,因此可让咱们的 Activity 以继承 DaggerAppCompatActivity 的方式来减小模板代码。api

DetailActivity 类以下:bash

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() {
        return fragmentDispatchingAndroidInjector;
    }
}
复制代码

让咱们的 DetailActivity 继承 DaggerAppCompatActivity 类,这样咱们就不用让 DetailActivity 类实现 HasSupportFragmentInjector 接口以及重写方法了。app

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() {}
}
复制代码

如今,是否是更简洁了。

DaggerApplication, AndroidInjector, AndroidSupportInjectionModule

看看还有哪些办法可以减小模板代码。我发现 AndroidInjector 可以帮助简化 AppComponent。你能够经过阅读 AndroidInjector 相关文档来获取相关信息。

下面是 AppComponent 类的代码。

@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);
}
复制代码

build()seedInstance() 方法已经在 AndroidInjector.Builder 抽象类中定义了,因此咱们的 Builder 类能够经过继承 AndroidInjection.Builder<Application> 来去掉上面代码中 application()build() 这两个方法。

一样的,AndroidInjector 接口中已经有 inject() 方法了。因此咱们能够经过继承 AndroidInjector<Application> 接口(接口是能够继承接口的)来删除 inject() 方法。

那么咱们简化后的 AppComponent 接口的代码以下:

@Component(modules = {
        AndroidSupportInjectionModule.class,
        AppModule.class,
        ActivityBuilder.class})
interface AppComponent extends AndroidInjector<AndroidSampleApp> {
    @Component.Builder
    abstract class Builder extends AndroidInjector.Builder<AndroidSampleApp> {}
}
复制代码

你有没有意识到咱们的 modules 属性也改变了?我从 @Component 注解的 modules 属性中移除了 AndroidInjectionModule.class 而且添加了 AndroidSupportInjectionModule.class。这是由于咱们使用的是支持库(v4库)的 Fragment。而 AndroidInjectionModule 是用来绑定 app 包的 Fragmentdagger。因此若是你想在 v4.fragment 中使用注入,那么你应该在你的 AppComponent modules 中添加 AndroidSupportInjectionModule.class

咱们改变了 AppComponent 的注入方式。那么 Application 类须要作什么改变。

DaggerActivityDaggerFragment 同样,咱们也让 Application 类继承 DaggerApplication 类。

以前的 Application 类的代码以下:

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() {
        return activityDispatchingAndroidInjector;
    }
}
复制代码

修改后代码以下:

public class AndroidSampleApp extends DaggerApplication {

    @Override
    protected AndroidInjector<? extends AndroidSampleApp> applicationInjector() {
        return DaggerAppComponent.builder().create(this);
    }
}
复制代码

源码

你能够从个人 GitHub 上获取修改后的源码。我没有把这些代码 merge 到主分支上,是由于我想在各个分支中保存 dagger 使用方式的历史记录。这样读者们就可以知道我是如何一步步简化 dagger 的使用方式。

PS.

我并非说这是 dagger 的最优美的实践方式。这只是我在本身项目中使用 dagger 的方式。若是喜欢的话,你也能够在本身的项目中这样使用。若是你实在不想让本身的 Application 类继承第三方的 Application 类就别这样使用(你能够把 DaggerApplication 的代码拷贝到你本身的App类里面,把 DaggerActivity/DaggerFragment 里面的代码拷贝到你本身的 BaseActivity/BaseFragment 中,若是你继承的是 AppCompatActivity 就使用 DaggerAppCompatActivity。 ),你高兴就好。最后,若是大家有更好的建议还请多多指教。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索