目录
2. 2.11版本@ContributesAndroidInjector
0. 为什么定制?
从 Dagger2入门 了解到,Dagger2的一个坑就是:
Component inject(container c) 容器必须传入与你实际调用inject相同的类。也就是说不能c传入BaseActivity,实际调用在XActivity。
也就是说如果我们用到了Dagger2,就必须每个Activity中去写一句如下的inject(this),肯定是不可能这么low的。
DaggerUserComponent.create().inject(this);
Dagger提供了两种方式解决:
- 2.10版本提供了相对复杂的解决方式
- 2.11版本@ContributesAndroidInjector简化流程
如果为了使用,直接使用ContributesAndroidInjector注解方式即可。
1. 2.10版本复杂的方式
此种方式主要是为了大致了解实现的逻辑,不具备实际开发用处。
1.0 导包
在Dagger的基础上新增Android定制支持。
// dagger2
implementation 'com.google.dagger:dagger:2.19'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
// dagger android
implementation 'com.google.dagger:dagger-android:2.19'
implementation 'com.google.dagger:dagger-android-support:2.19'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.19'
1.1 依赖创建
和之前一样,没啥说的。
package com.fengzhen.anddagger.old;
public class User {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
提供一个用户名为“小明”的Module
package com.fengzhen.anddagger.old;
import dagger.Module;
import dagger.Provides;
@Module
public class UserModule {
@Provides
User provideLoginXM() {
User login = new User();
login.setName("小明");
login.setPassword("123123");
return login;
}
}
1.2 依赖注入
这里就和之前不一样了,不再需要苦哈哈的去写inject(),只需要在BaseActivity继承Dagger-android提供的DaggerAppCompatActivity就可以了。
实际注入位置:
public class SecondActivity extends BaseActivity {
@Inject
User mLoginUser;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
// DaggerUserComponent.create().inject(this);
Log.i("fengzhen1", "onCreate: " + mLoginUser.getName());
}
}
BaseActivity也啥都没写:
package com.fengzhen.anddagger;
import android.os.Bundle;
import android.support.annotation.Nullable;
import dagger.android.support.DaggerAppCompatActivity;
/**
* 创建时间:2018/12/12
* 版 本:v1.0.0
* 作 者:fengzhen
* <p>
* 功能描述:什么都不用写,只需要继承 DaggerAppCompatActivity 就好了
*/
public class BaseActivity extends DaggerAppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
1.3 让这一切被Dagger所知晓
这也是做出改动的一个环节。还是1 2 3一步一步先实现功能。
1. 创建AppComponent。管理所有的子模块的Module。这里的BuildersModule相当于一个子模块;AndroidSupportInjectionModule 是Dagger-android提供的如四大组件、Fragment等的底层注入,后面简单看看。
package com.fengzhen.anddagger;
import javax.inject.Singleton;
import dagger.Component;
import dagger.android.AndroidInjector;
import dagger.android.support.AndroidSupportInjectionModule;
@Singleton
@Component(modules = {
BuildersModule.class,
AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<MyApplication> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<MyApplication> {
}
}
2. 子模块BuildersModule,绑定具体的UserComponent。(之前/之后 是2.11对比2.10 不用看)
package com.fengzhen.anddagger;
import android.app.Activity;
import com.fengzhen.anddagger.old.SecondActivity;
import com.fengzhen.anddagger.old.UserComponent;
import com.fengzhen.anddagger.old.UserModule;
import dagger.Binds;
import dagger.Module;
import dagger.android.ActivityKey;
import dagger.android.AndroidInjector;
import dagger.android.ContributesAndroidInjector;
import dagger.multibindings.IntoMap;
// ContributesAndroidInjector之前
@Module(subcomponents = UserComponent.class)
public abstract class BuildersModule {
@Binds
@IntoMap
@ActivityKey(SecondActivity.class)
abstract AndroidInjector.Factory<? extends Activity> bindSecondActivityInjectorFactory(
UserComponent.Builder builder
);
}
// ContributesAndroidInjector之后
//@Module
//public abstract class BuildersModule {
// @ContributesAndroidInjector(modules = UserModule.class)
// abstract SecondActivity secondActivityInjector();
//}
3. UserComponent主要是继承AndroidInjector,并传入Container泛型具体容器。(befor/after 是Dagger2基础和Dagger-android对比,不用看)
package com.fengzhen.anddagger.old;
import dagger.Subcomponent;
import dagger.android.AndroidInjector;
befor
//@Component(modules = UserModule.class)
//public interface UserComponent {
// void inject(SecondActivity secondActivity);
//}
/**
* 主要申明注入到的具体位置
*/
// after
@Subcomponent(modules = UserModule.class)
public interface UserComponent extends AndroidInjector<SecondActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<SecondActivity> {
}
}
4.创建MyApplication并且继承DaggerApplication,将整个逻辑链接起来,别忘了manifests进行注册。
package com.fengzhen.anddagger;
import dagger.android.AndroidInjector;
import dagger.android.DaggerApplication;
public class MyApplication extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().create(this);
}
}
如此,整个注入就完成。不再需要每个Container去inject,简直不要太爽。
1.4 源码看了一下 结合 生成的代码
1. DaggerAppCompatActivity主要就调用了一句代码 AndroidInjection.inject(this),然后与AppComponet关联,继而关联整个注入链。
2. MembersInjector<T> 通过泛型injectMembers()方法获得具体的——UserComponent传入的泛型SecondActivity——Container类型。实现在BaseActivity中进行具体的容器注入。
3. DaggerApplication实现HasActivityInjector接口,activityInjector()方法获取到全局的Application级别的AndroidInjector注入器。之后DaggerAppCompatActivity中inject(this)传入具体的容器注入。
4.AndroidSupportInjectionModule以及AndroidInjectionModule实现了具体的容器级别的注入,当然应用层级无法感知。
2. 2.11版本@ContributesAndroidInjector
BuildersModule改一下就可以了,而且UserComponent可以不写,可以不写。其他不变~~
package com.fengzhen.anddagger;
import com.fengzhen.anddagger.old.SecondActivity;
import com.fengzhen.anddagger.old.UserModule;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
// ContributesAndroidInjector之前
//@Module(subcomponents = UserComponent.class)
//public abstract class BuildersModule {
//
// @Binds
// @IntoMap
// @ActivityKey(SecondActivity.class)
// abstract AndroidInjector.Factory<? extends Activity> bindSecondActivityInjectorFactory(
// UserComponent.Builder builder
// );
//}
// ContributesAndroidInjector之后
@Module
public abstract class BuildersModule {
@ContributesAndroidInjector(modules = UserModule.class)
abstract SecondActivity secondActivityInjector();
}
纸上得来终觉浅,以后实际项目中用到了的时候在研究补充吧,比如侵入性太高的问题也还不知道对实际项目有什么影响。