1.Dagger2的简单使用
为什么需要使用Dagger2?
通过Dagger2
的目的是将程序分为三个部分。
- 实例化部分:对象的实例化。类似于容器,将类的实例放在容器中
- 调用者:需要实例化对象的类
- 沟通桥梁:利用Dagger2中的一些API将两者联系。
1.1.实例化部分(容器),在此处是Module
@Module //提供依赖对象的实例
public class MainModule {
@Provides // 关键字,标明该方法提供依赖对象
Person providerPerson(){
//提供Person对象
return new Person();
}
}
1.2 沟通部分Component
@Component(modules = MainModule.class) // 作为桥梁,沟通调用者和依赖对象库
public interface MainComponent {
//定义注入的方法
void inject(MainActivity activity);
}
1.3 使用者Activity
中调用
public class MainActivity extends AppCompatActivity{
@Inject //标明需要注入的对象
Person person;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 构造桥梁对象
MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();
//注入
component.inject(this);
}
}
看一下Person
类
public class Person {
public Person(){
Log.i("dagger","person create!!!");
}
}
我们来分析下调用过程:
- 创建Component(桥梁),并调用注入方法。
// 构造桥梁对象
MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();
//注入
component.inject(this);
- 查找当前类中带有
@Inject
的成员变量。
@Inject //标明需要注入的对象
Person person;
- 根据成员变量的类型从
Moudle
中查找哪个有@Providers
注解的方法返回值为当前类型。
@Provides // 关键字,标明该方法提供依赖对象
Person providerPerson(){
//提供Person对象
return new Person();
}
在使用过程出现了很多注解:
-
@Module
:作为实例对象的容器。 -
@Provides
:标注能够提供实例化对象的方法。 -
@Component
:作为桥梁,注入对象的通道。 -
@Inject
:需要注入的方法
2. @Singleton 单例注解
假如,对于同一个对象,我们需要注入两次,如下方式:
public class MainActivity extends AppCompatActivity{
@Inject
Person person;
@Inject
Person person2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 构造桥梁对象
MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();
//注入
component.inject(this);
// 打印两个对象的地址
Log.i("dagger","person = "+ person.toString()+"; person2 = "+ person2.toString());
}
}
看一下结果:
person = com.mahao.alex.architecture.dagger2.Person@430d1620;
person2 = com.mahao.alex.architecture.dagger2.Person@430d17c8
可见两个对象不一致。也就是说创建了两个对象。
可以在提供实例化对象的方法上添加@Singleton
注解
@Provides // 关键字,标明该方法提供依赖对象
@Singleton
Person providerPerson(){
return new Person();
}
同时,对于MainComponent也需要添加注解,不添加则会无法编译
@Singleton
@Component(modules = MainModule.class) // 作为桥梁,沟通调用者和依赖对象库
public interface MainComponent {
//定义注入的方法
void inject(MainActivity activity);
}
此时在Log,会发现两个对象的地址一样,可见是同一个对象。
那么不同的Activity之间,能否保持单例呢?
创建一个新的Activity,代码如下:
public class Main2Actvity extends AppCompatActivity {
@Inject
Person person;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 构造桥梁对象
MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule()).build();
//注入
component.inject(this);
Log.i("dagger","person = "+ person.toString());
}
}
结果如下:
person create!!!
person = com.mahao.alex.architecture.dagger2.Person@4310f898; person2 = com.mahao.alex.architecture.dagger2.Person@4310f898
person create!!!
person = com.mahao.alex.architecture.dagger2.Person@43130058
可见,@Singleton
只对一个Component
有效,即其单例所依赖Component
对象.
3.需要参数的实例化对象
Person
的构造方法发生了变化,需要传入一个Context
,代码如下:
public class Person {
private Context mContext;
public Person(Context context){
mContext = context;
Log.i("dagger","create");
}
}
这样的话,我们需要修改MainModule
@Module //提供依赖对象的实例
public class MainModule {
private Context mContext;
public MainModule(Context context){
mContext = context;
}
@Provides
Context providesContext(){
// 提供上下文对象
return mContext;
}
@Provides // 关键字,标明该方法提供依赖对象
@Singleton
Person providerPerson(Context context){
return new Person(context);
}
}
- 修改
providerPerson
方法,传入Context
对象。 - 添加
providesContext()
,用以提供Context
对象。
看一下使用
// 构造桥梁对象
MainComponent component = DaggerMainComponent.builder().mainModule(new MainModule(this)).build();
//注入
component.inject(this);
逻辑:
- 根据
@Inject
注解,查找需要依赖注入的对象。 - 从
MainModule
中根据返回值,找到providerPerson(Context context)
对象。 - 发现其需要传入参数
Context
,找到module
中具有返回值为Context的方法providersContext(). - 最后就成功的构建了实例化对象。
注:在编写Module中,不能出现传入参数和返回参数一致的情况,会导致死循环。
很容易理解,需要的和获取的是同一个方法,循环调用。
网友评论