0
点赞
收藏
分享

微信扫一扫

Dagger2——DI依赖注入——IOC原则的实现者


​​《如何获得完全松耦合的程序设计》​​ IoC原则、DIP原则、DI设计模式可以帮助我们获得完全松耦合的程序设计。而Dagger2则是实现了依赖注入(DI)设计模式的框架,也就是它实现了IoC原则。

简而言之,Dagger2在遵循IoC原则下帮助我们创建依赖对象。我大概讲一下DI设计模式:比说A类依赖B类,那么我们通过在A类外面创建B类的对象,再将其注入A类。需要有个第三方帮我们把这件事做了(IoC的体现),那么Dagger2就是这个第三方。

Dagger2是基于java规范要求,使用注解的方式生成代码。我们通过定义一些必要的部分,然后在编译时,Dagger2框架会使用我们定义的部分,去将这个“第三方”生成出来。
为了更好地讨论Dagger2我们先来了解一下Dagger2的相关术语:

  • Provider(提供者):​​@Module​​注解的类。负责提供注入的对象。
  • Consumer(消费者):​​@Inject​​用于定义依赖。
  • Connector(连接器):​​@Component​​注解的接口,这个接口定义了provider和consumer的连接。

我们通过一个例子来说明它的定义过程,及相关注解的使用。
如我们想使用Dagger2的技术,完成MainActivity类中context对象的创建。那么我们该如何做呢?
step1:定义Module
每一个module都以Module结尾,它是注入对象的提供者,必须用​​​@Module​​注解,等会就是由AppModule提供context对象的。

@Module
public class AppModule {
private Application application;

public AppModule(Application application) {
this.application = application;
}

@Provides
@Singleton
public Context provideContext() {
return application;
}
}

在提供注入对象的方法上必须使用​​@Provides​​​,而​​@Singleton​​​则表明注入的对象只初始化一次,是一个单例。
step2:定义Component
每一个Component都以Component结尾,它是一个接口,必须用​​​@Component​​​注解。它定义了注入对象提供者与消费者之间的关系。在这里就是注入对象提供者是​​AppModule​​​,而注入的对象的消费者是​​MainActivity​

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
void inject(MainActivity target);
}

step3:在Application里初始化AppComponent实例
DaggerAppComponent实现了AppComponent接口,一开始它是不存在的,所以做一步之前,先build编译一下,这个类就会被生成出来。

private AppComponent component;

@Override
public void onCreate() {
super.onCreate();

//needs to run once to generate it
component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();

}


public AppComponent getComponent() {
return component;
}

step4:在消费者里使用@Inject注入对象

public class MainActivity extends AppCompatActivity {
// 注入点
@Inject
Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 向AppComponent接口实例的inject方法传入当前对象,那么Dagger2就会把帮我们把对象注入到当前对象来
((App) getApplication()).getComponent().inject(this);

}
}

当我们配置了上面这些必要部分后,biuld编译时,Dagger2会把这个“第三方”的所有代码给生成出来。如:

Dagger2——DI依赖注入——IOC原则的实现者_android

DaggerAppComponent.java:

// Generated by Dagger (https://google.github.io/dagger).
package com.wong.dagger2demo;

import android.content.Context;
import dagger.internal.DoubleCheck;
import dagger.internal.Preconditions;
import javax.inject.Provider;

public final class DaggerAppComponent implements AppComponent {
private Provider<Context> provideContextProvider;

private DaggerAppComponent(Builder builder) {

initialize(builder);
}

public static Builder builder() {
return new Builder();
}

@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideContextProvider =
DoubleCheck.provider(AppModule_ProvideContextFactory.create(builder.appModule));
}

@Override
public void inject(MainActivity target) {
injectMainActivity(target);
}

private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectContext(instance, provideContextProvider.get());
return instance;
}

public static final class Builder {
private AppModule appModule;

private Builder() {}

public AppComponent build() {
Preconditions.checkBuilderRequirement(appModule, AppModule.class);
return new DaggerAppComponent(this);
}

public Builder appModule(AppModule appModule) {
this.appModule = Preconditions.checkNotNull(appModule);
return this;
}
}
}

AppModule_ProvideContextFactory.java:

// Generated by Dagger (https://google.github.io/dagger).
package com.wong.dagger2demo;

import android.content.Context;
import dagger.internal.Factory;
import dagger.internal.Preconditions;

public final class AppModule_ProvideContextFactory implements Factory<Context> {
private final AppModule module;

public AppModule_ProvideContextFactory(AppModule module) {
this.module = module;
}

@Override
public Context get() {
return provideInstance(module);
}

public static Context provideInstance(AppModule module) {
return proxyProvideContext(module);
}

public static AppModule_ProvideContextFactory create(AppModule module) {
return new AppModule_ProvideContextFactory(module);
}

public static Context proxyProvideContext(AppModule instance) {
return Preconditions.checkNotNull(
instance.provideContext(), "Cannot return null from a non-@Nullable @Provides method");
}
}

MainActivity_MembersInjector.java:

// Generated by Dagger (https://google.github.io/dagger).
package com.wong.dagger2demo;

import android.content.Context;
import dagger.MembersInjector;
import javax.inject.Provider;

public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<Context> contextProvider;

public MainActivity_MembersInjector(Provider<Context> contextProvider) {
this.contextProvider = contextProvider;
}

public static MembersInjector<MainActivity> create(Provider<Context> contextProvider) {
return new MainActivity_MembersInjector(contextProvider);
}

@Override
public void injectMembers(MainActivity instance) {
injectContext(instance, contextProvider.get());
}

public static void injectContext(MainActivity instance, Context context) {
instance.context = context;
}
}

如果我们再添加需要注入的字段:

@Module
public class AppModule {
private Application application;

public AppModule(Application application) {
this.application = application;
}

@Provides
@Singleton
public Context provideContext() {
return application;
}
@Provides
public String provideName(){
return "Hello world";
}
}
public class MainActivity extends AppCompatActivity {
@Inject
Context context;
@Inject
String name;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((App) getApplication()).getComponent().inject(this);

}
}

再次编译得到:

Dagger2——DI依赖注入——IOC原则的实现者_java_02


由此可以看出Dagger2会为每个注入的对象生成一个工厂类。


举报

相关推荐

0 条评论