[譯] 全新 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前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索