//非常简单的一个活动
class MainActivity : AppCompatActivity() {
@Inject
lateinit var a: String//待注入的变量
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerMainComponent.builder()
.mainModule(MainModule())
.build()
.inject(this)//注入
Log.d("=============", a)//打印看看结果
}
}
//提供字符串的module
@Module
class MainModule {
@Provides
fun provideString(): String = "123"
}
@Component(modules = arrayOf(MainModule::class))
interface MainComponent {
fun inject(activity: Activity)
}
貌似操作都没错呀,然后结果如下:
Error: lateinit property a has not been initialized所以这是为什么呢,还是看看Dagger生成的Inject方法是怎么工作的吧,说不定从这能找到答案
@Override
public void inject(Activity activity) {
MembersInjectors.noOp().injectMembers(activity);
}
上面就是生成的inject方法了,显然要往injectMembers里面挖
//跳进来发现这是个空方法,那就一定有他的实现类了
void injectMembers(T instance);
//========== 实现1 ===========
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.a = aProvider.get();
}
//========== 实现2 ===========
@Override public void injectMembers(Object instance) {
checkNotNull(instance);
}
可以看到,实现1中就对我们要注入的字符串a进行了赋值,而实现2中只是检查了一下目标类是不是空的。而实现1的对象是这样(<Activity>noOp())才能拿到的
//正确
MembersInjectors.noOp().injectMembers(activity);
//错误
MembersInjectors.noOp().injectMembers(activity);
也就是说我们的inject方法参数写错了,只要吧MainComopnent中inject的参数改为MainActivity就好了
@Component(modules = arrayOf(MainModule::class))
interface MainComponent {
fun inject(activity: MainActivity)
}
再跑一下:=============: 123
@Module
class MainModule {
@Provides
@Singleton//单例??
fun provideString(): String = "123"
}
把Module中的provide方法加上@Singleton注解后就是单例了?,编译一下…
Error:Execution failed for task ‘:app:kaptDebugKotlin’.
Internal compiler error. See log for more details
再看看Gradle Console中的日志:
Component (unscoped) may not reference scoped bindings
原来,对应的Comopnent要加上同样的标记才可以
@Singleton
@Component(modules = arrayOf(MainModule::class))
interface MainComponent {
fun inject(activity: MainActivity)
}
再跑一下,编译通过了
再来看看@Singleton
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
原来Singleton是一种作用域注解,Component和Module中的provide方法作用域注解相同才能实现单例
之前是这样写的,中间传入了Module
DaggerMainComponent.builder()
.mainModule(MainModule())
.build()
.inject(this)
把它去掉,照样工作
DaggerMainComponent.builder()
.build()
.inject(this)
再去看看Dagger生成的代码
public MainComponent build() {
if (mainModule == null) {
this.mainModule = new MainModule();
}
return new DaggerMainComponent(this);
}
原来,build方法会自动生成Module,所以可以不传入,拿什么时候才要传入Module呢?修改一下Module,在构造方法中传入参数
@Module
class MainModule(val activity: MainActivity) {
@Provides
@Singleton
fun provideString(): String = "123"
}
编译之后再来看看生成的方法
public MainComponent build() {
if (mainModule == null) {
throw new IllegalStateException(MainModule.class.getCanonicalName() + " must be set");
}
return new DaggerMainComponent(this);
}
卧槽,变了…当Module有参数的时候就需要手动传入了,否则会抛异常。。