看完不懂Dagger2我跪搓板
0. 序言
- 有些人说现在的架构都是Mvp+Dagger2,其实好多公司还是没有用Dagger2,因为项目的更新换代不是一天就能完成的,公司项目需要的终极目标其实是稳定,就算你不用Dagger2,依然可以实现预期的效果。但是使用了Dagger2的项目,代码层面解耦更好,所以Dagger2是每个Android开发都应该熟练掌握的,就像Java后台开发熟练掌握Spring一样。
- 博文主要分为三大部分:注解、懒加载和原理分析。注解包括:
① @Inject 和 @Component
② @Module 和 @Provides
③ @Named 和 @Qualifier
④ @Singleton和@Scope
⑤ @Component的dependencies
- 由于Dagger2使用场景比较多,一篇文章不能写得全面,还请理解。
- 看完你会发现:如果你不懂,可以先写出来,可能写出来就懂了;如果你懂得不多,可以慢慢来,总有茅塞顿开的那一刻,总之就是"永不放弃"。
- 书中示例代码的下载地址:https://github.com/OnlyYouMyLove/Test_Dagger2/tree/master
Git地址:https://github.com/OnlyYouMyLove/Test_Dagger2.git
1. 所涉及依赖:
annotationProcessor 'com.google.dagger:dagger-compiler:2.7'
implementation 'com.google.dagger:dagger:2.7'
implementation 'com.google.code.gson:gson:2.8.5'
2. @Inject 和 @Component
- 定义两个类,分别是MainActivity和Person,并在MainActivity中执行Person的eat方法
public class Person{
public void eat(){
Log.i("fukq","我要吃面包");
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Person person = new Person();
person.eat();
}
}
11-27 14:47:51.695 32317-32317/com.smartisan.dagger2 I/fukq: 我要吃面包
- 用Dagger2改造以上示例:
2.1. 改写Person类:
public class Person{
@Inject
public Person() {
}
public void eat(){
Log.i("fukq","我要吃面包");
}
}
说明:这里标记Person构造方法,则表明Dagger2可以使用Person构造方法构建对象。
2.2. 创建接口MainActivityComponent指定依赖注入的目标类:
@Component
public interface MainActivityComponent {
void inject(MainActivity activity);
}
说明:
① 接口命令建议:目标类名+Component。
② @Component 就是告诉Dagger2依赖注入的目标是MainActivity。
③ 创建完接口后记得编译下:锤子按钮(AndroidStudio)。这样在编译后Dagger2就会为我们生成名为Dagger+目标类名+Component的辅助类,辅助类的默认生成路径如下:
image.png
2.3. 在目标类MainActivity中使用辅助类DaggerMainActivityComponent完成注入:
public class MainActivity extends AppCompatActivity {
@Inject
Person mPerson; // 1
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.create().inject(this); // 2
mPerson.eat();
}
}
说明:
① Inject用来标记需要注入的实例,这个实例是以成员变量的形式出现。
② 辅助类DaggerMainActivityComponent调用inject完成注入。
③ 总结可知:Inject有三种注入方式,分别是成员变量注入和构造方法注入以及方法注入(后面会讲)。
11-27 14:57:24.679 32691-32691/com.smartisan.dagger2 I/fukq: 我要吃面包
3. @Module 和 @Provides
3.1 Dagger2引入第三方类库
如果项目使用第三方的类库,比如Gson,我们就不能把@Inject添加到Gson的构造方法中,这个时候采用@Module和@Provides来处理。
3.1.1. 创建GsonModule类:
@Module
public class GsonModule {
@Provides
public Gson provideGson(){
return new Gson();
}
}
说明:
① @Module用来告诉Component,可以从这个类获取依赖对象。
② 告诉了对象所在的类,还需要告诉Component获取依赖对象实例的方法,所以用@Provides注释方法。
3.1.2. 编写Component类MainActivityComponent:
@Component(modules = GsonModule.class)
public interface MainActivityComponent {
void inject(MainActivity activity);
}
说明:
① 之前已经创建了MainActivityComponent类,添加modules = GsonModule.class即可
② modules = GsonModule.class用来指定module,之所以用modules,是因为可以指定多个Module.
3.1.3. 在MainActivity中使用Gson:
public class MainActivity extends AppCompatActivity {
@Inject
Gson mGson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.create().inject(this);
String jsonData = "{'name':'fukq','age':18}";
Man man = mGson.fromJson(jsonData,Man.class);
Log.i("fukq","name-------"+man.getName());
}
}
public class Man{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
11-27 16:36:54.512 3275-3275/com.smartisan.dagger2 I/fukq: name-------fukq
3.2 Dagger2引入抽象对象
除了第三方仓库的引入不能使用@Inject,如果注入的对象是抽象的,那么@Inject也无法使用,因为抽象的类并不能实例化。比如:
public abstract class Engine {
public abstract String work();
}
public class GasolineEngline extends Engine {
@Inject
public GasolineEngline() {
}
@Override
public String work() {
return "汽油发动机发动";
}
}
public class Car {
private Engine mEngine;
@Inject
public Car(Engine engine) {
mEngine = engine;
}
public String run(){
return mEngine.work();
}
}
说明:这里用的Inject的构造方法注入。可能你会问哪种注入方式更好呢,这里建议构造方法注入,以后会专门拿出一篇文章来讲解这个事情。
public class MainActivity extends AppCompatActivity {
@Inject
Person mPerson;
@Inject
Gson mGson;
@Inject
Car mCar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.create().inject(this);
mPerson.eat();
String jsonData = "{'name':'fukq','age':18}";
Man man = mGson.fromJson(jsonData,Man.class);
Log.i("fukq","name-------"+man.getName());
String str =mCar.run();
Log.d("fukq","car---" + str);
}
}
error: com.smartisan.dagger2.Engine cannot be provided without an @Provides-annotated method.
com.smartisan.dagger2.Engine is injected at
com.smartisan.dagger2.Car.<init>(engine)
com.smartisan.dagger2.Car is injected at
com.smartisan.dagger2.MainActivity.mCar
com.smartisan.dagger2.MainActivity is injected at
com.smartisan.dagger2.MainActivityComponent.inject(activity)
说明:
① 这里报错了,为何呢?因为Engine是抽象的。@Inject无法提供实例。
② 这里采用@Module和@Provides来处理。
3.2.1. 修改GasolineEngline类,去掉@Inject:
public class GasolineEngline extends Engine {
@Override
public String work() {
return "汽油发动机发动";
}
}
3.2.2. 创建EngineModule:
@Module
public class EngineModule {
@Provides
public Engine provideEngline(){
return new GasolineEngline();
}
}
3.2.3. 在Component中指定EngineModule:
@Component(modules = {GsonModule.class,EngineModule.class})
public interface MainActivityComponent {
void inject(MainActivity activity);
}
3.2.4. 在MainActivity 注入Car:
public class MainActivity extends AppCompatActivity {
@Inject
Person mPerson;
@Inject
Gson mGson;
@Inject
Car mCar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.create().inject(this);
mPerson.eat();
String jsonData = "{'name':'fukq','age':18}";
Man man = mGson.fromJson(jsonData,Man.class);
Log.i("fukq","name-------"+man.getName());
String str =mCar.run();
Log.d("fukq","car---" + str);
}
}
11-28 11:23:20.858 19873-19873/? D/fukq: car---汽油发动机发动
4. @Named 和 @Qualifier
4.1 @Named
@Qualifier是限定符,@Named是@Qualifier的一种实现。当有两个类都继承同一个父类或者均实现同一个接口。当他们被提供给高层时,Component就不知道到底要提供哪一个依赖对象了。比如上面的汽车(父类),它有一个子类GasolineEngline,我们再提供一个子类DieselEngine给汽车(父类),如下:
public class DieselEngline extends Engine {
@Override
public String work() {
return "柴油发动机发动";
}
}
@Module
public class EngineModule {
@Provides
public Engine provideGasoline(){
return new GasolineEngline();
}
@Provides
public Engine provideDiesel(){
return new DieselEngline();
}
}
这个时候我们提供了两个Provides,Component不知道选哪个,这个时候@Named就派上了用场,它的作用就是起别名(外号)。
4.1.1 对EngineModule进行改造:
@Module
public class EngineModule {
@Provides
@Named ("Gasoline")
public Engine provideGasoline(){
return new GasolineEngline();
}
@Provides
@Named ("Diesel")
public Engine provideDiesel(){
return new DieselEngline();
}
}
4.1.2 在Car类(父类)指定要采用哪个Provides:
public class Car {
private Engine mEngine;
@Inject
public Car(@Named("Diesel") Engine engine) {
mEngine = engine;
}
public String run(){
return mEngine.work();
}
}
11-28 14:10:18.815 22163-22163/com.smartisan.dagger2 D/fukq: car---柴油发动机发动
4.2 @Qualifier
@Named 传递的值只能是字符串,而@Qualifier 则更灵活一些,@Qualifier不是直接标记在属性上的,而是用来自定义注解的,如下:
4.2.1 定义两个不同的注解(自定义注解以后会写一篇博文来讲解)
@Qualifier
@Retention(RUNTIME)
public @interface Gasloline {
}
@Qualifier
@Retention(RUNTIME)
public @interface Diesel {
}
说明:只定义两个不同名称的注解即可,空实现即可,因为我们就是通过不同的注解区分Provides,以便让Component找到所要找的实例。记得导包:
import static java.lang.annotation.RetentionPolicy.RUNTIME;
4.2.2 修改EngineModule类:
@Module
public class EngineModule {
@Provides
@Gasloline
public Engine provideGasoline(){
return new GasolineEngline();
}
@Provides
@Diesel
public Engine provideDiesel(){
return new DieselEngline();
}
}
4.2.3 在Car类(父类)指定要采用哪个注解(即用哪个Provides):
public class Car {
private Engine mEngine;
@Inject
public Car(@Gasloline Engine engine) {
mEngine = engine;
}
public String run(){
return mEngine.work();
}
}
11-28 14:36:27.832 22846-22846/com.smartisan.dagger2 D/fukq: car---汽油发动机发动
5. @Singleton和@Scope
5.1 @Singleton
@Scope是用来自定义注解的,而@Singleton是用来配合实现局部单例和全局单例的。注意:@Singleton本身不具备创建单例的能力。我们从示例来分析
@Inject
Gson mGson;
@Inject
Gson mGson2;
Log.d("fukq",mGson.hashCode()+"");
Log.d("fukq",mGson2.hashCode()+"");
210706522
73949835
上面是两个Gson的实例,分别是mGson和mGson2,打印了两个实例的内存地址,内存地址不同说明它们不是一个对象,那如果我们想让Gson在MainActivity中是单例,咋弄呢?这个时候@Singleton就派上用场了。
5.1.1 修改GsonModule,添加@Singleton:
@Module
public class GsonModule {
@Singleton
@Provides
public Gson provideGson(){
return new Gson();
}
}
5.1.2 在MainActivityComponent中添加@Singleton:
@Singleton
@Component(modules = {GsonModule.class,EngineModule.class})
public interface MainActivityComponent {
void inject(MainActivity activity);
}
我们再次打印两个Gson对象的内存地址值,结果如下:
11-28 15:32:39.425 25927-25927/? D/fukq: 73949835
11-28 15:32:39.425 25927-25927/? D/fukq: 73949835
说明:这个时候我们发现Gson在MainActivity中是单例,那么我们再创建一个SecondActivity,SecondActivity创建的Gson的内存地址和MainActivity中的是一样的吗?答案是:肯定不一样。因为我们只在MainActivityComponent中添加@Singleton,意思是只在MainActivity中是单例的。那如何实现全局单例呢?我们创建一个全局的Component,也就是说Component保证只有一个实例。如何保证Component只有一个实例呢?我们在Application中初始化即可。
5.2 @Scope
我们看下@Singleton的源码:
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
我们发现,它是用@Scope来修饰的。所以这里我们不用@Singleton来实现全局实例,我们用@Scope仿写一个:之所以仿写,一来可以清楚看到@Scope的作用,二来可以自定义注解的名称(总是叫Singleton,很单调)。
5.2.1 定义@ApplicationScope注解:
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationScope {
}
5.2.2 在GsonModule中使用@ApplicationScope:
@Module
public class GsonModule {
@ApplicationScope
@Provides
public Gson provideGson(){
return new Gson();
}
}
5.2.3 创建ActivityComponent来处理多个Activity:
@ApplicationScope
@Component(modules = GsonModule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
void inject(SecondActivity mainActivity);
}
5.2.4 创建App类继承Application,用来提供ActivityCompenent实例:
public class App extends Application {
ActivityComponent mActivityComponent;
@Override
public void onCreate() {
super.onCreate();
mActivityComponent = DaggerActivityComponent.builder().build();
}
public static App get(Context context){
return (App) context.getApplicationContext();
}
ActivityComponent getActivityComponent(){
return mActivityComponent;
}
}
5.2.5 使用全局的Component来注入Gson:
public class MainActivity extends AppCompatActivity {
@Inject
Gson mGson;
@Inject
Gson mGson2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
App.get(MainActivity.this).getActivityComponent().inject(this);
Log.d("fukq:MainActivity",mGson.hashCode()+"");
Log.d("fukq:MainActivity",mGson2.hashCode()+"");
findViewById(R.id.bt_skip_to_second).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
}
public class SecondActivity extends AppCompatActivity {
@Inject
Gson mGson;
@Inject
Gson mGson2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContentView(R.layout.activity_main);
App.get(SecondActivity.this).getActivityComponent().inject(this);
Log.d("fukq:SecondActivity",mGson.hashCode()+"");
Log.d("fukq:SecondActivity",mGson2.hashCode()+"");
}
}
11-28 17:06:28.703 29041-29041/? D/fukq:MainActivity: 150530801
150530801
11-28 17:06:44.454 29041-29041/com.smartisan.dagger2 D/fukq:SecondActivity: 150530801
11-28 17:06:44.454 29041-29041/com.smartisan.dagger2 D/fukq:SecondActivity: 150530801
说明:
① 发现MainActivity和SecondActivity中的Gson的内存地址一样,也就是实现了Gson的全局单例。
② 利用@Scope可以更好地管理Component和Module之间的匹配关系。比如编译器会检查Component管理的Module,若发现管理的Module中的标注创建实例方法的Scope注解与Component中的Scope注解不一致,就会报错。
③ 一般来说会有一个全局的Component,每个界面有自己的Component,当然不是必需,如果页面之间的依赖的类是一样的,可以共用一个Component。
6. @Component的dependencies
@Component可以用dependencies依赖于其他Component。这里我们让ActivityComponent依赖SuperComponent。
6.1 创建类SuperMan:
public class SuperMan {
@Inject
public SuperMan() {
}
public String fighting(){
return "欲为大树,莫与草争";
}
}
6.2 创建SuperModule和SuperComponent:
@Module
public class SuperManModule {
@Provides
public SuperMan provideSuperMan(){
return new SuperMan();
}
}
@Component(modules = SuperManModule.class)
public interface SuperManComponent {
SuperMan getSuperMan();
}
6.3 在ActivityComponent中引入SuperManComponent:
@ApplicationScope
@Component(modules = GsonModule.class,dependencies = SuperManComponent.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
void inject(SecondActivity mainActivity);
}
注意:每次更新Component记得编译下,对应As的小锤子。
6.4 在此前定义的App类中引入SuperManComponent,修改App代码:
public class App extends Application {
ActivityComponent mActivityComponent;
@Override
public void onCreate() {
super.onCreate();
mActivityComponent = DaggerActivityComponent.builder().superManComponent(DaggerSuperManComponent.builder().build()).build();
}
public static App get(Context context){
return (App) context.getApplicationContext();
}
ActivityComponent getActivityComponent(){
return mActivityComponent;
}
}
说明:可以对照之前App的代码,不难发现,只是对ActivityComponent的生成进行修改,修改后可以体现出来SuperManComponent和ActivityComponent的依赖关系。
6.5 在MainActivity中使用SuperMan:
public class MainActivity extends AppCompatActivity {
@Inject
SuperMan mSuperMan;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
App.get(MainActivity.this).getActivityComponent().inject(this);
String str = mSuperMan.fighting();
Log.d("fukq", "onCreate: str" + str);
}
}
11-29 11:36:27.348 10510-10510/com.smartisan.dagger2 D/fukq: onCreate: str欲为大树,莫与草争
7. 懒加载
Dagger2 提供了懒加载,就是在注入实例的时候不实例化,而是在使用的时候,调用get方法来 获取实例。修改SuperMan的注入,代码如下:
public class MainActivity extends AppCompatActivity {
@Inject
Lazy<SuperMan> mSuperManLazy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
App.get(MainActivity.this).getActivityComponent().inject(this);
SuperMan superMan = mSuperManLazy.get();
String str = superMan.fighting();
Log.d("fukq", "onCreate: str" + str);
}
}
11-29 11:47:43.576 10925-10925/com.smartisan.dagger2 D/fukq: onCreate: str欲为大树,莫与草争
8. Dagger2 原理分析
因为Dagger2的应用场景比较多,我们这里进行原理分析,拿Person注入的例子,例子代码我再复制下,省去大家往前面翻:
public class Person{
@Inject
public Person() {
}
public void eat(){
Log.i("fukq","我要吃面包");
}
}
@Component
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
}
public class MainActivity extends AppCompatActivity {
@Inject
Person mPerson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainActivityComponent.create().inject(this);
mPerson.eat();
}
}
8.1 看下核心代码
DaggerMainActivityComponent.create().inject(this);
说明:这里是核心代码,我们第一看create方法,第二看inject方法,看清楚两个方法的实现逻辑就能够明白Dagger的核心Component到底做了什么事情,也就能明白Dagger的实现原理。
public final class DaggerMainActivityComponent implements MainActivityComponent {
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainActivityComponent(Builder builder) {
assert builder != null;
initialize(builder); // 4
}
public static Builder builder() {
return new Builder(); // 2
}
public static MainActivityComponent create() {
return builder().build(); // 1
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create()); // 5
}
@Override
public void inject(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity); // 6
}
public static final class Builder {
private Builder() {}
public MainActivityComponent build() {
return new DaggerMainActivityComponent(this); // 3
}
}
}
说明:
① Component就是Dagger核心逻辑所在,所以我们看DaggerMainActivityComponent做了什么。
② 一步一步看,由表及里:
先看create()方法,执行的是代码 1 处 :
public static MainActivityComponent create() {
return builder().build(); // 1
}
再看builder()方法:
public static Builder builder() {
return new Builder(); // 2
}
接着看build()方法:
public MainActivityComponent build() {
return new DaggerMainActivityComponent(this); // 3
}
代码3执行的DaggerMainActivityComponent的构造方法,并传入Builder对象:
private DaggerMainActivityComponent(Builder builder) {
assert builder != null;
initialize(builder); // 4
}
再接着看initialize()方法,拿到了MembersInjector对象,引用是mainActivityMembersInjector:
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create()); // 5
}
拿到mainActivityMembersInjector引用后,它干了点啥呢:
@Override
public void inject(MainActivity mainActivity) {
mainActivityMembersInjector.injectMembers(mainActivity); // 6
}
接着看injectMembers方法:
public interface MembersInjector<T> {
/**
* Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
* absence of an injectable constructor.
*
* <p>Whenever the object graph creates an instance, it performs this injection automatically
* (after first performing constructor injection), so if you're able to let the object graph
* create all your objects for you, you'll never need to use this method.
*
* @param instance into which members are to be injected
* @throws NullPointerException if {@code instance} is {@code null}
*/
void injectMembers(T instance);
}
发现它是接口MembersInjector的方法,那谁实现了这个接口呢,点左边小原绿色图标:会发现是名为MainActivity_MembersInjector的类,这个名字好熟悉,原来往上退两步,就是代码 5:
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create()); // 5
}
我们又看到了MainActivity_MembersInjector这类,那弄清楚它的类里面的injectMembers和create(Person_Factory.create())方法应该就能分析出来原理了,代码:
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<Person> mPersonProvider;
public MainActivity_MembersInjector(Provider<Person> mPersonProvider) {
assert mPersonProvider != null;
this.mPersonProvider = mPersonProvider; // 2
}
public static MembersInjector<MainActivity> create(Provider<Person> mPersonProvider) {
return new MainActivity_MembersInjector(mPersonProvider); // 1
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mPerson = mPersonProvider.get();
}
public static void injectMPerson(MainActivity instance, Provider<Person> mPersonProvider) {
instance.mPerson = mPersonProvider.get();
}
}
因为create方法先于injectMembers方法调用,我们先看create方法:
public static MembersInjector<MainActivity> create(Provider<Person> mPersonProvider) {
return new MainActivity_MembersInjector(mPersonProvider); // 1
}
会发现调用了MainActivity_MembersInjector类的构造方法:
public MainActivity_MembersInjector(Provider<Person> mPersonProvider) {
assert mPersonProvider != null;
this.mPersonProvider = mPersonProvider; // 2
}
这个构造方法传进来的是什么呢?我们往上看
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(Person_Factory.create());
会发现Person_Factory.create(),那这里做了什么呢?
public enum Person_Factory implements Factory<Person> {
INSTANCE;
@Override
public Person get() {
return new Person();
}
public static Factory<Person> create() {
return INSTANCE;
}
}
原来是一个枚举单例 create()方法,返回的是Person_Factory,但是MainActivity_MembersInjector的构造方法的参数是Provider<Person> mPersonProvider,和Person_Factory啥关系呢?怎么就可以直接传入了,看Person_Factory的超类Factory<Person>代码:
public interface Factory<T> extends Provider<T> {
}
原来Factory<Person>的超类是Provider<T>,怪不得可以直接传入呢。那现在我们看看传进来的这个参数Provider<Person> mPersonProvider 干了点啥呢:
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.mPerson = mPersonProvider.get();
}
原来是在injectMembers方法中,这样正好不用额外去分析injectMembers方法了,instance是MainActivity的引用, instance.mPerson就是它的成员变量Person对象的引用mPerson,那有了引用了,等号右边是什么呢?
public enum Person_Factory implements Factory<Person> {
INSTANCE;
@Override
public Person get() {
return new Person();
}
public static Factory<Person> create() {
return INSTANCE;
}
}
往上看:看到了get方法的返回是
return new Person();
看到这里,我们发现讲了这么多,这3个辅助类的作用就是调用inject方法的时候,将新创建的Person实例赋值给MainActivity的成员变量Person。其中Person_Factory用来生产Person的实例,MainActivity_MembersInjector用来把Person的实例赋值给MainActivity的成员变量Person,而DaggerMainActivityComponent就是为了把两者给串联起来。而这就是Dagger的实现原理。
这里我们还看出了,单一职责原则和建造者设计模式的引用,建议平时多看看源码,会让我们受益匪浅。一起加油!
9. 后续
如果大家喜欢这篇文章,欢迎点赞;如果想看更多 Dagger 方面的技术,欢迎关注!