只有Inject的模式
-
activity(Inject成员变量,告诉dagger拿到对象之后赋值给它)
@Inject lateinit var person: Person override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) DaggerMainComponent.builder().build().injectMain(this) }
-
Component
@Component interface MainComponent{ fun injectMain(activity: MainActivity) }
-
需要inject拿到的对象(告诉dagger我要拿到这个类的对象)
class Person @Inject constructor() { }
@Inject有两项职责:
- 注解构造函数:通过标记构造函数,告诉Dagger 2可以创建该类的实例(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖关系。
- 注解依赖变量:通过标记依赖变量,Dagger2提供依赖关系,注入变量
创建好这三个类要先build一下,然后会自动生成对应的Component类。
先看看生成的DaggerMainComponent类源码
public final class DaggerMainComponent implements MainComponent {
private DaggerMainComponent(Builder builder) {}
public static Builder builder() {
return new Builder();
}
public static MainComponent create() {
return new Builder().build();
}
@Override
public void injectMain(MainActivity activity) {
injectMainActivity(activity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectPerson(instance, new Person());
return instance;
}
public static final class Builder {
private Builder() {}
public MainComponent build() {
return new DaggerMainComponent(this);
}
}
}
可以看到DaggerMainComponent.builder().build()和DaggerMainComponent.create()效果是一样的。
编译之后生成了对应的Injector类
person对象是在injectMainActivity方法中new出来的。
MainActivity_MembersInjector.injectPerson(instance, new Person());
再看看Injector的源码
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<Person> personProvider;
public MainActivity_MembersInjector(Provider<Person> personProvider) {
this.personProvider = personProvider;
}
public static MembersInjector<MainActivity> create(Provider<Person> personProvider) {
return new MainActivity_MembersInjector(personProvider);
}
@Override
public void injectMembers(MainActivity instance) {
injectPerson(instance, personProvider.get());
}
public static void injectPerson(MainActivity instance, Person person) {
instance.person = person;
}
}
然后直接赋值到activity类的成员变量中
public static void injectPerson(MainActivity instance, Person person) {
instance.person = person;
}
Inject、Module、Provide完整模式
有时候只用Inject不能获取到对象了,比如person是一个第三方库类,这样你就不能直接Inject它的构造方法了,这个时候就需要module和provide
-
activity
class MainActivity : AppCompatActivity() { @Inject lateinit var person: Person override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) DaggerMainComponent.builder().module(Module()).build().injectMain(this) Log.d("eee=person", "" + person.hashCode()) } }
-
Component(Module可以多个,逗号隔开)
@Component(modules = [Module::class]) interface MainComponent{ fun injectMain(activity: MainActivity) }
-
Module
@Module class Module { @Provides fun providePerson():Person{ return Person() } }
-
person
class Person {}
可以看到这个示例代码中其实就是在module中创建好了对象,最后传到activity中的。
DaggerMainComponent中的关键代码是injectMain
@Override
public void injectMain(MainActivity activity) {
injectMainActivity(activity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectPerson(
instance, Module_ProvidePersonFactory.proxyProvidePerson(module));
return instance;
}
调用Module_ProvidePersonFactory的proxyProvidePerson,就是拿module中你创建的那个对象
public static Person proxyProvidePerson(Module instance) {
return Preconditions.checkNotNull(
instance.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
}
MainActivity_MembersInjector.injectPerson就是最后的赋值操作了
public static void injectPerson(MainActivity instance, Person person) {
instance.person = person;
}
当person有多个构造函数并Inject了多个构造的时候,provide不知道要提供哪个构造方法,将造成“依赖迷失”
IntoSet、IntoMap
-
activity
class MainActivity : AppCompatActivity() { @Inject lateinit var bananaSet:Set<BananaBean> @Inject lateinit var setBananaBean: SetBananaBean @Inject lateinit var bananaByString:Map<String,BananaBean> @Inject lateinit var bananaByClass:Map<Class<*>,BananaBean> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val build = DaggerMainComponent.builder().build() build.injectMain(this) val banana = build.setBanana() Log.d("eee=banana1",banana.toString()) Log.d("eee=banana2",banana.toString()) Log.d("eee=banana3",banana.toString()) Log.d("eee=bananaSet",bananaSet.toString()) Log.d("eee=setBananaBean",setBananaBean.toString()) Log.d("eee=component string",build.bananaByString().toString()) Log.d("eee=component class",build.bananaByClass().toString()) Log.d("eee=Inject string",bananaByString.toString()) Log.d("eee=Inject class",bananaByClass.toString()) } }
-
module
@Module class DrinkModule { @Provides @IntoSet fun providerBanana(): BananaBean { return BananaBean("特朗普香蕉") } } @Module class FruitModule { @Provides @IntoSet fun providerBanana(): BananaBean { return BananaBean("特朗普--香蕉") } } @Module class MultiModule { @Provides @ElementsIntoSet fun providerBananaSet(): Set<BananaBean> { var set = HashSet<BananaBean>() set.add(BananaBean("布什香蕉")) set.add(BananaBean("约翰逊香蕉")) return set } @Provides @IntoMap @StringKey("a") fun providerBananaMap(): BananaBean { return BananaBean("a apple") } @Provides @IntoMap @ClassKey(Person::class) fun providerClassMap(): BananaBean { return BananaBean("class apple") } }
-
bean(kotlin中不要像Java那样单独写个方法写构造,否则inject无效)
class SetBananaBean @Inject constructor(val set:Set<BananaBean>) { override fun toString(): String { return super.toString() } } class BananaBean(val s:String) { override fun toString(): String { return s } }
-
Component
@Component(modules = [Module::class,FruitModule::class,DrinkModule::class,MultiModule::class]) interface MainComponent{ fun injectMain(activity: MainActivity) fun setBanana():Set<BananaBean> fun bananaByString():Map<String,BananaBean> fun bananaByClass():Map<Class<*>,BananaBean> }
-
运行结果
D/eee=banana1: [特朗普香蕉, 约翰逊香蕉, 特朗普--香蕉, 布什香蕉] D/eee=banana2: [特朗普香蕉, 约翰逊香蕉, 特朗普--香蕉, 布什香蕉] D/eee=banana3: [特朗普香蕉, 约翰逊香蕉, 特朗普--香蕉, 布什香蕉] D/eee=bananaSet: [布什香蕉, 约翰逊香蕉, 特朗普香蕉, 特朗普--香蕉] D/eee=setBananaBean: com.example.admin.baladagger2.test1.SetBananaBean@676e725 D/eee=component string: {a=a apple} D/eee=component class: {class com.example.admin.baladagger2.test1.Person=class apple} D/eee=Inject string: {a=a apple} D/eee=Inject class: {class com.example.admin.baladagger2.test1.Person=class apple}
查看源码知道关键代码在DaggerMainComponent类,继承MainComponent重写setBanana方法
@Override
public Set<BananaBean> setBanana() {
return SetBuilder.<BananaBean>newSetBuilder(3)
.add(FruitModule_ProviderBananaFactory.proxyProviderBanana(fruitModule))
.add(DrinkModule_ProviderBananaFactory.proxyProviderBanana(drinkModule))
.addAll(MultiModule_ProviderBananaSetFactory.proxyProviderBananaSet(multiModule))
.build();
}
public MainComponent build() {
if (fruitModule == null) {
this.fruitModule = new FruitModule();
}
if (drinkModule == null) {
this.drinkModule = new DrinkModule();
}
if (multiModule == null) {
this.multiModule = new MultiModule();
}
return new DaggerMainComponent(this);
}
@Override
public void injectMain(MainActivity activity) {
injectMainActivity(activity);
}
private MainActivity injectMainActivity(MainActivity instance) {
MainActivity_MembersInjector.injectBananaSet(instance, setBanana());
MainActivity_MembersInjector.injectSetBananaBean(instance, getSetBananaBean());
MainActivity_MembersInjector.injectBananaByString(instance, bananaByString());
MainActivity_MembersInjector.injectBananaByClass(instance, bananaByClass());
return instance;
}
多个component不能同时inject到一个类中
例如:
A component中有 fun inject(Bala:Activity)
B component中也有 fun inject(Bala:Activity)
dependencies
使用场景:你需要的对象中需要其他的对象,例如“车”需要有”颜色“
-
Car
class Car(val brand:String,val color:VehicleColor) { fun go(){ Log.d("eee=car",brand+"go --color is"+color.color) } }
-
CarComponent
@Component(modules = CarModule.class, dependencies = ColorComponent.class) public interface CarComponent { void inject(CarActivity activity); }
-
CarModule
@Module public class CarModule { @Provides Car provideCar(VehicleColor color){ return new Car("兰博基尼",color); } }
-
ColorComponent
@Component(modules = ColorModule.class) public interface ColorComponent { VehicleColor carColor(); }
-
ColorModule
@Module public class ColorModule { @Provides VehicleColor provideCarColor(){ return new VehicleColor("红色"); } }
-
Component2
@Component(modules = [Module2::class],dependencies = [MainComponent::class]) interface Component2 { fun inject(activity:Test2) }
-
Module2
@Module class Module2 { @Provides fun provideTest2():Person2{ return Person2() } }
-
VehicleColor
class VehicleColor(val color:String)
-
CarActivity
class CarActivity: AppCompatActivity() { @Inject lateinit var car: Car override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) DaggerCarComponent.builder().colorComponent(DaggerColorComponent.create()).build().inject(this) car.go() } }
-
运行结果
D/eee=car: 兰博基尼go --color is红色
-
分析
- 看了下Car这个类,需要color这个字符串,是怎么传进去的
- 没有直接操作CarModule,怎么创建出的car对象
首先直接看inject这个方法做了啥?在DaggerCarComponent中可以看到
@Override
public void inject(CarActivity activity) {
injectCarActivity(activity);
}
private CarActivity injectCarActivity(CarActivity instance) {
CarActivity_MembersInjector.injectCar(instance, getCar());
return instance;
}
private Car getCar() {
return CarModule_ProvideCarFactory.proxyProvideCar(
carModule,
Preconditions.checkNotNull(
colorComponent.carColor(), "Cannot return null from a non-@Nullable component method"));
}
getCar方法中拿到的就是car的对象,里面传入carModule和colorComponent,module中有car的对象的方法,component中有car所需要的颜色。然后在CarModule_ProvideCarFactory中创建中car对象
public static Car proxyProvideCar(CarModule instance, VehicleColor color) {
return Preconditions.checkNotNull(
instance.provideCar(color), "Cannot return null from a non-@Nullable @Provides method");
}
car就是这样创建和传递的。现在的问题是carModule和colorComponent是怎么出来的。在DaggerCarComponent的Builder类中可以看到
public static final class Builder {
private CarModule carModule;
private ColorComponent colorComponent;
private Builder() {}
public CarComponent build() {
if (carModule == null) {
this.carModule = new CarModule();
}
if (colorComponent == null) {
throw new IllegalStateException(ColorComponent.class.getCanonicalName() + " must be set");
}
return new DaggerCarComponent(this);
}
public Builder carModule(CarModule carModule) {
this.carModule = Preconditions.checkNotNull(carModule);
return this;
}
public Builder colorComponent(ColorComponent colorComponent) {
this.colorComponent = Preconditions.checkNotNull(colorComponent);
return this;
}
}
虽然CarModule没有直接操作,但是build方法中判断为空的时候会自动new出来,然后赋值给DaggerCarComponent的成员变量carModule。colorComponent是你自己传进去的(通过DaggerColorComponent.create())
public final class DaggerColorComponent implements ColorComponent {
private ColorModule colorModule;
private DaggerColorComponent(Builder builder) {
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static ColorComponent create() {
return new Builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.colorModule = builder.colorModule;
}
@Override
public VehicleColor carColor() {
return ColorModule_ProvideCarColorFactory.proxyProvideCarColor(colorModule);
}
public static final class Builder {
private ColorModule colorModule;
private Builder() {}
public ColorComponent build() {
if (colorModule == null) {
this.colorModule = new ColorModule();
}
return new DaggerColorComponent(this);
}
public Builder colorModule(ColorModule colorModule) {
this.colorModule = Preconditions.checkNotNull(colorModule);
return this;
}
}
}
关键代码来了,在build方法中可以看到,里面new了一个ColorModule出来,ColorModule中就提供了获取VehicleColor也就是颜色对象的方法。然后把ColorModule对象赋值给Builder类的成员变量,再new一个DaggerColorComponent(this),这个this就是保存了ColorModule对象的Builder。然后在DaggerColorComponent里面又把Builder中colorModule拿出来保存在自己的成员变量中,此时DaggerColorComponent也就拿到了颜色。
最后还是一样的套路,拿到了car构造所需要的参数(在DaggerColorComponent中),拿到了可以创建car的方法(在carModule中),然后再用inject赋值
Subcomponent
-
Bike
class Bike(val color: String) { fun go(){ Log.d("eee=bike","bike is running -- color is "+color) } }
-
BikeComponent
@Subcomponent(modules = BikeModule.class) public interface BikeComponent { Bike supplyBike(); @Subcomponent.Builder interface Builder{ Builder bikeModule(BikeModule module); BikeComponent build(); } }
-
BikeModule
@Module public class BikeModule { @Provides Bike provideCar(){ return new Bike(" black "); } }
-
Brand
class Brand(val name:String) { override fun toString(): String { return "Brand{ $name }" } }
-
BrandComponent
@Component(modules =[ BrandModule::class]) interface BrandComponent { fun inject(activity: BikeActivity) fun supplyBikeComponentBuild():BikeComponent.Builder }
-
BrandModule
@Module(subcomponents = [BikeComponent::class]) class BrandModule { @Provides fun provideBrand(): Brand { return Brand("林肯加长版") } }
-
BikeActivity
class BikeActivity: AppCompatActivity() { @Inject lateinit var brand: Brand override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val brandComponent = DaggerBrandComponent.builder().build() brandComponent.inject(this) val supplyBike = brandComponent.supplyBikeComponentBuild().build().supplyBike() supplyBike.go() Log.d("eee=brand",brand.toString()) } }
-
运行结果
D/eee=bike: bike is running -- color is black D/eee=brand: Brand{ 林肯加长版 }
-
源码都是类似的,没有分析的意义
https://www.jianshu.com/p/5fd066bf28fa