概述
之前我們使用dagger注入時,都需要activity、fragment等宿主在component中註冊,比如:
((SomeApplicationBaseType) getContext().getApplicationContext())
.getApplicationComponent()
.activity(this)
.build()
.inject(this);
這樣之後纔可以使用該component中的依賴實例(也可以是父組件中能拿到的),隨着開發的深入,這類代碼越來越多,很不利於重構,同時也打破了依賴注入的核心原則:一個類不應該知道如何注入它。
Dagger.Android庫是Dagger庫的補充,dagger.android中的類提供了一種簡化此模式的方法,從而在一定程度上避免了上述問題的發生。
使用流程
1.在ApplicationComponent中注入AndroidInjectionModule,如果項目中用到v4包的Fragment,還需注入AndroidSupportInjectionModule.建議把兩個Module都注入ApplicationComponent中:
@Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule,...})
public interface ApplicationComponent {
void inject(MyApplication application);
}
2.創建Android庫的核心類(Activity、Fragment、Service、IntentService、BroadcasReceiver),需要注意的就是:AndroidInjection.inject(T)方法的調用位置
- 在Activity、Service及IntentService的onCreate()中,super.onCreate()方法以前。
- 在Fragment中onAttach()中,super.onAttach()方法以前。如果是v4包的Fragment,應調用AndroidSupportInjection.inject()方法。
- 在BroadcastReceiver的onReceive()中,super.onReceive之前調用。
3.創建子組件 - @Subcomponent,其繼承自AndroidInjector,而T就是step2創建的Android庫的類型
@Subcomponent
public interface CoffeeReceiverSubcomponent extends AndroidInjector<CoffeeReceiver> {
@Subcomponent.Builder
public abstract class Builder extends AndroidInjector.Builder<CoffeeReceiver> {
}
}
4.創建Module,其subcomponents屬性值就是3創建的子組件。在其內必須聲明一個抽象方法,該抽象方法返回AndroidInjector.Factory<?>實例,而其參數爲3創建的XxSubcomponent.Builder實例。
@Module(subcomponents = CoffeeReceiverSubcomponent.class)
public abstract class CoffeeModule {
@Binds
@IntoMap
@BroadcastReceiverKey(CoffeeReceiver.class)
abstract AndroidInjector.Factory<? extends BroadcastReceiver> bind(CoffeeReceiverSubcomponent.Builder builder);
}
5.將創建的Module注入到ApplicationComponent中,即把其添加至ApplicationComponent的modules屬性列表
@Component(modules = {AndroidInjectionModule.class, AndroidSupportInjectionModule.class, CoffeeModule.class, ...})
public interface TodoComponent extends AndroidInjector<TodoApplication> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<TodoApplication> {
}
}
6.創建自定義Application,繼承了DaggerApplication,因爲dagger把該添加的DispatchingAndroidInjector添加進去了。但是,並沒有實現v4包的HasSupportFragmentInjector,這裏需要手動添加進去。
public class TodoApplication extends DaggerApplication implements HasSupportFragmentInjector{
@Inject
DispatchingAndroidInjector<Fragment> fragmentSupportInjector;
public void onCreate() {
super.onCreate();
}
@Override
protected AndroidInjector<TodoApplication> applicationInjector() {
return DaggerTodoComponent.builder().create(this);
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return fragmentSupportInjector;
}
}
注意:只有當BroadcastReceiver在AndroidManifest.xml中註冊時,才能使用DaggerBroadcastReceiver。 當在動態註冊BroadcastReceiver時,推薦使用構造函數注入。
官方demo使用方式
官方demo中的使用方式簡潔方便,主要是使用了一個註解—@ContributesAndroidInjector
@Target(METHOD)
public @interface ContributesAndroidInjector {
// 要注入到生成的dagger.Subcomponent中的Module。
Class<?>[] modules() default {};
}
官方文檔對它是這麼解釋的:爲其註解的方法生成相應的AndroidInjector。該注射器是 dagger.Subcomponent的實現
- 此註釋必須應用於返回具體的Android框架類型(例如:FooActivity、BarFragment、MyService等)的Module中的抽象方法。
- 該方法應該沒有參數。
具體可看官方例子mvp-dagger
1.自定義一個application,繼承DaggerApplication:
public class ToDoApplication extends DaggerApplication {
@Inject
TasksRepository tasksRepository; // component中暴露出來
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().application(this).build();
}
}
2.創建一個管理全局的component:
@Singleton
@Component(modules = {TasksRepositoryModule.class,
ApplicationModule.class,
ActivityBindingModule.class,
AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<ToDoApplication> {
TasksRepository getTasksRepository();
// Gives us syntactic sugar. we can then do DaggerAppComponent.builder().application(this).build().inject(this);
// never having to instantiate any modules or say which module we are passing the application to.
// Application will just be provided into our app graph now.
@Component.Builder
interface Builder {
@BindsInstance
AppComponent.Builder application(Application application);
AppComponent build();
}
}
3.創建一個ActivityBindingModule用於管理所有應用內的activity(子組件)
@Module
public abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector(modules = TasksModule.class)
abstract TasksActivity tasksActivity();
@ActivityScoped
@ContributesAndroidInjector(modules = AddEditTaskModule.class)
abstract AddEditTaskActivity addEditTaskActivity();
@ActivityScoped
@ContributesAndroidInjector(modules = StatisticsModule.class)
abstract StatisticsActivity statisticsActivity();
@ActivityScoped
@ContributesAndroidInjector(modules = TaskDetailPresenterModule.class)
abstract TaskDetailActivity taskDetailActivity();
}
4.每個activity都可以再通過module屬性繼續提供依賴或子組件
@Module
public abstract class TasksModule {
@FragmentScoped
@ContributesAndroidInjector
abstract TasksFragment tasksFragment();
@ActivityScoped
@Binds abstract TasksContract.Presenter taskPresenter(TasksPresenter presenter);
}
如上的tasksFragment()中 @ContributesAndroidInjector也可以有module繼續依賴下去
TasksRepositoryModule可以當做一個全局的數據module,ApplicationModule可以提供一些全局實例,如網球請求的client等等,AndroidSupportInjectionModule則是使用v4包時需要注入的。
總結
擴展庫可以使dagger的使用更爲簡單方便,具體的需要查看官方demo學習後多加練習細細體會