该文章默认你已经掌握了Dagger2的常规使用。
如果对Dagger2的概念还不是很清楚,可以参考:
Dagger Android产生的原因??
- 对象使用者如果需要使用 Inject 注解生成的对象,需要知道其注入器(比如:DaggerxxxComponent),它打破了依赖注入的原则:一个类不应该知道如何注入它。
- 随着项目代码的增多,类似 DaggerxxxComponent.buider().build().inject() 这样的模板代码也会越来越多,使得后期很难重构。
Dagger2 2.1x新特性
解决了Dagger2 2.10之前的两个明显的缺陷,被注入者不需要知道其注入者。
依赖
//dagger2 依赖
implementation 'com.google.dagger:dagger:2.16'
//dagger2 android依赖,一般直接依赖dagger-android-support,其内部默认依赖了dagger-android
//implementation 'com.google.dagger:dagger-android:2.16'
//添加了android support的支持
implementation 'com.google.dagger:dagger-android-support:2.16'
//dagger注解处理器
annotationProcessor 'com.google.dagger:dagger-compiler:2.16'
//dagger android注解处理器
annotationProcessor 'com.google.dagger:dagger-android-processor:2.16'
使用步骤
1. 被依赖类:在构造函数上使用@Inject
注解声明
public class Student {
private String name;
@Inject
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2. 使用依赖对象
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@Inject
Student student;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "student ---- " + student.toString());
}
}
如果直接这样运行肯定是直接NullPoint,因为student还没有被注入到MainActivity之中。
那Student对象又是如何注入的呢?
3. 实现依赖对象和使用者的绑定
-
自定义Application继承DaggerApplication(注意导包,使用dagger.android.support.DaggerApplication)
这一步是实现自动注入的前提
public class DemoApp extends DaggerApplication { @Override protected AndroidInjector<? extends DaggerApplication> applicationInjector() { return null; //这里先暂时返回null } }
-
我们知道需要将对象注入到使用者之中,要通过Component,那我们先创建MainComponent,使用
@SubComponent
注解(为什么是使用SubComponent呢??)@Subcomponent public interface MainComponent extends AndroidInjector<MainActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<MainActivity>{} }
这段代码是模板代码,只需要修改AndroidInjector<T>中的泛型,改成需要注入的对象,也就是MainActivity
-
有了MainComponet,就需要将其注入到MainActivity之中
2.10之前,是通过这行代码
DaggerMainComponet.builder().build().inject(this);
实现的。现在Dagger2会帮我们自动实现注入,但是需要告诉Dagger2哪些Activity需要被注入。
新建ActivityBindingModule类:
@Module(subcomponents = {MainComponent.class}) public abstract class ActivityBindingModule { @Binds @IntoMap @ActivityKey(MainActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindMainActivityInjectorFactory(MainComponent.Builder builder); }
可以看到,这个module里面依赖了MainComponent,所以MainComponent需要使用
@SubComponet
注解,注入的代码也是通过MainComponent中的抽象方法 Builder 生成的。上面这段代码的作用:生成
Map<Activity.class, AndroidInjector.Factory<? extends Activity>>
的map,并将MainActivity的注入器放入其中。 -
创建AppComponent, 在modules中添加 AndroidSupportInjectionModule.class, ActivityBindModule.class,执行make project
@Component(modules = {AndroidSupportInjectionModule.class, ActivityBindModule.class}) public interface AppComponent extends AndroidInjector<DemoApp> { @Component.Builder abstract class Builder extends AndroidInjector.Builder<DemoApp>{ } }
-
make完成后会生成DaggerAppComponent类,在DemoApp中返回
@Override protected AndroidInjector<? extends DaggerApplication> applicationInjector() { return DaggerAppComponent.builder().create(this); }
-
最后在MainActivity中添加
AndroidInjection.inject(this);
public class MainActivity extends AppCompatActivity { @Inject Student student; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidInjection.inject(this); setContentView(R.layout.activity_main); Log.e(TAG, "student ---- " + student.toString()); } }
这一步也可以通过修改Acitivty的基类,省略
public class MainActivity extends DaggerActivity{ ... } //在DaggerActivity的源码中,可以看到内部已经我们添加了这行代码 @Beta public abstract class DaggerActivity extends Activity implements HasFragmentInjector { @Inject DispatchingAndroidInjector<Fragment> fragmentInjector; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); } @Override public AndroidInjector<Fragment> fragmentInjector() { return fragmentInjector; } }
上面就是完整的注入流程,所有的模板代码Dagger Android都已经帮我们处理好了,我们需要做的只是处理依赖注入关系。
大致的流程:
image但是这么多步骤,难免会产生错误,而且学习成本也增加了很多,好在Dagger2 2.11之后新增了@ContributesAndroidInjector
简化了注入过程(这个后面分析)。
网友评论