1、为什么要使用Dagger2
和Spring的思想一样, 传统创建对象需要主动new 的方式,IOC技术则是实现被动注入的方式。称之为依赖注入,也可以称之为控制反转。目的就是为了代码的解耦。
2、Dagger2的简单使用
(1)添加Dagger2注解处理器和API支持
implementation 'com.google.dagger:dagger:2.4'
annotationProcessor 'com.google.dagger:dagger-compiler:2.4'
根据Gradle的依赖,由此可猜到Dagger2使用到了APT注解处理器的技术,必然在Dagger2的API支持中需要使用到注解,并且Dagger2会根据注解生成相应的代码。
(2)测试注入一个Dog对象
- 创建一个Dog类
package com.example.dagger2demo.bean;
/**
* author : weishixiong
* e-mail : weishixiong@pudutech.com
* date : 2022/2/18 11:22
* desc :Dog实体类
*/
public class Dog {
}
- 创建Module,使用@Module注解将对象包裹,并开放提供Dog对象的方法
package com.example.dagger2demo.module;
import com.example.dagger2demo.bean.Dog;
import dagger.Module;
import dagger.Provides;
/**
* author : weishixiong
* e-mail : weishixiong@pudutech.com
* date : 2022/2/18 11:33
* desc :Dog类包裹、提供对象
*/
@Module
public class DogModule {
@Provides
public Dog provideDogObject() {
return new Dog();
}
}
- 创建Component接口,将对象注入到指定的目标中,例子为注入到MainActivity中
package com.example.dagger2demo.component;
import com.example.dagger2demo.MainActivity;
import com.example.dagger2demo.module.DogModule;
import com.example.dagger2demo.module.PigModule;
import dagger.Component;
/**
* author : weishixiong
* e-mail : weishixiong@pudutech.com
* date : 2022/2/18 11:35
* desc :对象注入
*/
@Component(modules = {DogModule.class, PigModule.class})
public interface MyComponent {
/**
* 此处不能用多态
*
* @param activity
*/
void inject(MainActivity activity);
}
- 在MainActivity中注入对象
package com.example.dagger2demo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.example.dagger2demo.bean.Dog;
import com.example.dagger2demo.bean.Pig;
import com.example.dagger2demo.component.DaggerMyComponent;
import javax.inject.Inject;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
@Inject
Dog dog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMyComponent.create().inject(this);
}
public void click(View view) {
Log.e(TAG, "click: " + dog.hashCode());
}
}
2022-02-18 11:48:38.099 26775-26775/com.example.dagger2demo E/MainActivity: click: 9641581
dog对象打印出了hashcode,说明我们的对象已经注入成功。
通过一张图了解大概的注入流程:

3、源码分析(APT生成代码的部分省略)
(1)编译期使用APT生成对应的代码

(2)在MainAcrtivity初始化的时候调用 DaggerMyComponent.create().inject(this);
调用DaggerMyComponent.create()的时候创建DaggerMyComponent对象,我们在创建的对象的时候看源码发生了什么?
private Provider<Dog> provideDogObjectProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
..........
private void initialize(final Builder builder) {
this.provideDogObjectProvider = DogModule_ProvideDogObjectFactory.create(builder.dogModule);
this.mainActivityMembersInjector =
MainActivity_MembersInjector.create(provideDogObjectProvider, providerPigObjectProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private DogModule dogModule;
private Builder() {}
public MyComponent build() {
if (dogModule == null) {
this.dogModule = new DogModule();
}
return new DaggerMyComponent(this);
}
....
}
- 创建DaggerMyComponent对象的时候创建了DogModule对象,调用DogModule_ProvideDogObjectFactory.create,将DogModule包装到DogModule_ProvideDogObjectFactory provideDogObjectProvider 对象中。
- 调用MainActivity_MembersInjector.create方法将provideDogObjectProvider 对象包装到MainActivity_MembersInjector对象中。
再来看看inject方法,最终调用到了MainActivity_MembersInjector中的injectMembers方法,
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.dog = dogProvider.get();
}
到这里就就很明显了将MainActivity中的dog对象赋值为 dogProvider.get();,而dogProvider中的get方法最后会调用我们的DogModule中的provideDogObject方法
@Override
public Dog get() {
return Preconditions.checkNotNull(
module.provideDogObject(), "Cannot return null from a non-@Nullable @Provides method");
}
@Module
public class DogModule {
@Provides
public Dog provideDogObject() {
return new Dog();
}
}
到这里MainActvity中的dog对象就有值了,而这个值正式我们再DogModule 中通过provideDogObject方法提供的。
(3)源码小结
- Module负责包装、提供对象
- Component拿到Module提供的对象注入到指定的目标中(比如例子中的MainActivity)
网友评论