- 原文地址:New Android Injector with Dagger 2 — part 3
- 原文作者:Mert Şimşek
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:woitaylor
- 校對者:corresponding shengye102
全新 Android 注入器 : Dagger 2(三)
如果你還沒有閱讀(一)和(二),我建議你先閱讀它們。
概要
你可以使用 DaggerActivity
,DaggerFragment
,DaggerApplication
來減少 Activity/Fragment/Application
類裡面的模板程式碼。
同樣的,在 dagger
的 component
中,你也可以通過 AndroidInjector<T>
去減少模板程式碼。
DaggerAppCompatActivity and DaggerFragment
在使用 dagger
的 fragment
或者 activity
中要記得呼叫 AndroidInjection.inject()
方法。
同樣的,如果你想要在 v4
包裡面的 fragment
中使用 Injection
,你應該讓你的 activity
實現 HasSupportFragmentInject
介面並且重寫 fragmentInjector
方法。
最近,我把這些相關程式碼移到 BaseActivity
和 BaseFragment
。因為與其在每個 activity
中宣告這些,還不如把共同的程式碼放到基類裡面。
於是我在研究 dagger
專案的時候發現 DaggerAppCompatActivity
、DaggerFragment
這些類正好是我所需要的。如果說 Android
喜歡繼承,那麼我們也可以假裝喜歡繼承 ?
讓我們看看這些類做了些神馬。
@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
的方式來減少模板程式碼。
DetailActivity
類如下:
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
介面以及重寫方法了。
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
包的 Fragment
到 dagger
。所以如果你想在 v4.fragment
中使用注入,那麼你應該在你的 AppComponent modules
中新增 AndroidSupportInjectionModule.class
。
我們改變了 AppComponent
的注入方式。那麼 Application
類需要做什麼改變。
跟 DaggerActivity
和 DaggerFragment
一樣,我們也讓 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
。 ),你高興就好。最後,如果你們有更好的建議還請多多指教。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。