一、问题背景
通过 @Inject 和 @Component 已经实现了 DI,那么为什么 Dagger2 还要实现其他的DI 方式。
其实在上文中我们实现的 DI 方式中我们不难发现,通过@Inject 的注解实体类的构造函数是必不可少,它标识着 Dagger2 可以实例化该类。那么当你需要实例化一个第三方的对象时,是不是懵逼了,因为你不可能注解第三方类的构造函数 – 比如说 Gson 类的构造函数。那么现在就需要 @Module 来充分发挥作用了。
二、解决方案
什么是 Module
其实Module 其实是一个简单工厂模式,Module 里面的方法都是创建相应类实例的方法。
具体什么是 简单工厂模式,请看代码段简单学习设计模式 – 简单工厂模式
栗子:通过 @Module 的方式获得第三方类库的对象 – Gson(当然也可以获得自定义类对象)
@Module
public class AModule {
@Provides
public Gson provideGson(){
return new Gson();
}
}
你再该类中看到了两个注解:
通过 @Module 注解类
通过 @Provides 注解方法
添加多个 Module
一个 Component 可以含有多个 Module ,这样在寻找依赖实例时就会自动从多个 Module 中寻找。
添加 多个 Module 的方法有两种:
Component 注解 – Component(modules={××××,×××})
示例代码如下:
@Component(modules={ModuleA.class,ModuleB.class,ModuleC.class})
public interface AppComponent{
...
}
Module 注解 – @Module(includes={××××,×××})
示例代码如下:
@Module(includes={ModuleA.class,ModuleB.class,ModuleC.class})
public class FruitModule{
...
}
@Component(modules={FruitModule.class}) //添加多个Module
public interface AppComponent{
...
}
这种使用 Module的 includes 添加多Module 的方法一般用于构建更高层的Module时候使用,如在本例中
什么是 Provides
@Provides 用以标注 Module 类中的方法,它的作用是 标注该 Module 可以向外界提供的类的实例对象的方法 ,就像 AModule 中可以提供 Gson 实例对象的 provideGson() 方法。 3. Component – 管理 Module
此时 DI 不是通过 @Inject 注解类构造器的方式,那么这个注解器的使用方法肯定也有所变化。
此时 Component 的职责是管理 Module,Component 中的属性允许 Module 可以加入到 Component,同时一个 Component 可以加入多个 Module。
依赖注入的具体工作流程: 协作流程 若实例化过程中参数同样是需要依赖注入的,那么需要按照上图中的流程一样寻找相应的方法。如果遍历了组件中管理的 Module 类中的 @Provides 注解的方法,那么就会寻找该实例类的构造器中是否有被 @Inject 注解的,如果参数同样有需要依赖注入的,那么就重复以上过程。如果最终还是没有找到相应的初始化实例的方法,那么程序会报出相应的错误。
三、案例
public class UserTwo {
private String mName = "jack chen";
private int mAge = 40;
public UserTwo(String mName, int mAge) {
this.mName = mName;
this.mAge = mAge;
}
public String getName() {
return mName;
}
public void setName(String mName) {
this.mName = mName;
}
public int getAge() {
return mAge;
}
public void setAge(int mAge) {
this.mAge = mAge;
}
}
@Module
public class UserTwoModule {
@Provides
UserTwo provideUserTwo(){
return new UserTwo("男",1243);
}
}
@Component(modules = UserTwoModule.class)
public interface UserTwoComponent {
void injectToSecondActivity(SecondActivity mSecondActivity);
}
public class SecondActivity extends AppCompatActivity {
@Inject
UserTwo mUserTwo;
private static final String TAG = "SecondActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_second);
DaggerUserTwoComponent.builder().userTwoModule(new UserTwoModule()).build().injectToSecondActivity(this);
Log.e(TAG,"name : " + mUserTwo.getName() + " age :" + mUserTwo.getAge());
}
}
注:DaggerUserTwoComponent 为编译时产生的,需要编译后导入