目錄
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();
}
紙上得來終覺淺,以後實際項目中用到了的時候在研究補充吧,比如侵入性太高的問題也還不知道對實際項目有什麼影響。