理解 Dagger2 的源碼
Dagger2 幫助我們將被注入類自動地注入到目標類堡僻,有利解耦找岖,從而讓維護項目的依賴關系變得輕松姐刁。
通過代碼實現(xiàn)一下 dagger 是如何實現(xiàn)依賴注入铃诬,我們創(chuàng)建一個類 DataManager 用作被注入的類。
public class DataManager {
private static final String TAG = "DataManager";
public DataManager() {
Log.d(TAG, "DataManager: ininial");
}
}
然后我們需要 DataManager 注入到目標中 MainActivity座哩,因為 MainActivity 并不是由我們開發(fā)人員直接創(chuàng)建的徒扶,是由系統(tǒng)創(chuàng)建,所以我們需要將一些依賴以屬性的形式進行注入
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
好我們就開始來實現(xiàn)根穷,要進行注入姜骡,如果熟悉 dagger 知道我們需要一個 module 類和一個 component 接口
首先 Module 負責提供要注入的類的對象,在 Dagger 中我們需要 @Module 來修飾為了是 apt 能夠識別到這個類進行代碼生成工作屿良。
public class AppModule {
public DataManager provideManager(){
return new DataManager();
}
}
然后 Component 負責將被注入類注入到目標類中圈澈,在 Dagger 中我們需要注解 @Component 以及將 @Component 以及已經(jīng)定義依賴的 module
public interface AppComponent {
void inject(MainActivity activity);
}
最后我們還需要 MainActivity 中做一些事
public class MainActivity extends AppCompatActivity {
public DataManager dataManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ScAppComponent.builder()
.appMoudle(new AppModule())
.build() //使用構(gòu)建者模式創(chuàng)建一個 Component 實例
.inject(this);
}
}
需要做兩件事
- 將 DataManager 作為屬性,需要是 public 類型
在編譯過程會用到 apt 技術生成一些類用來實現(xiàn)尘惧,這里我們就手動寫這些類
通常使用時我們通常會以這種形式來實現(xiàn)康栈,
DaggerAppComponent
.builder()
.appModule(new AppModule())
.build()
.inject(this)
appModule 應該代碼生成時根據(jù) AppModule 生成方法,通過 builder 可看出來這里使用構(gòu)建者的設計模式喷橙。我們這里手動地完成代碼生成以便了解 dagger 是如何將類 DataManager 注入到 MainActivity
我們先寫 ScAppComponent 這個自動生成的類谅将,在 Dagger 命名應該為 DaggerAppComponent,這里我用我習慣的 Sc 開頭以便區(qū)別重慢,這里 ScAppComponent 實現(xiàn)之前定義好的 AppComponent 接口,實現(xiàn) inject 方法逊躁,這個方法指定要將 DataManager 注入的位置似踱。
public class ScAppComponent implements AppComponent{
private Provider<DataManager> provideManagerProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
public ScAppComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
private void initialize(final Builder builder){
this.provideManagerProvider = (Provider<DataManager>) AppModule_ProvideManagerFactory.create(builder.appModule);
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(provideManagerProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static Builder builder(){
return new Builder();
}
public static AppComponent create(){
return builder().build();
}
public static final class Builder{
private AppModule appModule;
private Builder(){}
public AppComponent build(){
if(appModule == null){
this.appModule = new AppModule();
}
return new ScAppComponent(this);
}
public Builder appMoudle(AppModule appModule){
// this.appModule = Preconditions.checkNotNull(appModule)
return this;
}
}
}
- 調(diào)用 builder 方法時核芽,會返回一個內(nèi)部靜態(tài)類 Builder 的實例
public static Builder builder(){
return new Builder();
}
-
內(nèi)部靜態(tài)類 Builder ,這是一般構(gòu)建者的模式的 Builder,然后調(diào)用 Builder 類的 build 方法看代碼會給我們返回一個 AppComponent 然后我們看代碼 build
- 先創(chuàng)建了一個 AppModule
- 然后將 Builder 自己作為參數(shù)傳入給 AppComponent 構(gòu)造函數(shù)創(chuàng)建一個 AppComponent 實例哮独。
-
在 AppComponent 構(gòu)造函數(shù)中會調(diào)用 initialize 方法
private void initialize(final Builder builder){ this.provideManagerProvider = (Provider<DataManager>) AppModule_ProvideManagerFactory.create(builder.appModule); this.mainActivityMembersInjector = MainActivity_MembersInjector.create(provideManagerProvider); }
在 initialize 方法中皮璧,會初始化
private Provider<DataManager> provideManagerProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
這里我們在分別看一下這兩個 AppModule_ProvideManagerFactory 和 MainActivity_MembersInjector 他們倆也是通過 APT 生成悴务,所以我們一步一步寫一寫譬猫,來了解他們都做了什么,先看 AppModule_ProvideManagerFactory 叨恨,看名字應該是一個工廠類特碳,用于生成 DataManager 實例的吧晕换。
public final class AppModule_ProvideManagerFactory implements Factory<DataManager> {
private final AppModule module;
public AppModule_ProvideManagerFactory(AppModule module) {
assert module != null;
this.module = module;
}
@Override
public DataManager get() {
return module.provideManager();
}
public static Factory<DataManager> create(AppModule module){
return new AppModule_ProvideManagerFactory(module);
}
}
我們從 create 入手益愈,這里返回一個 Factory<DataManager> 類型的對象那么我們就簡單定義一下。Factory<T> 作為一個接口擴展了 Provider<T>接口
public interface Factory<T> extends Provider<T>{
}
所以定義一下Provider<T> 有一個方法 get 用于返回我們創(chuàng)建好的(要注入的)實例
public interface Provider<T> {
T get();
}
好準備好了所需的接口,我們再回到 AppModule_ProvideManagerFactory 這需要實現(xiàn) Factory<T> 接口,用于提供產(chǎn)品的工廠吧
這里的 get 方法中是調(diào)用我們 module(AppModule)的 provideManager 方法來返回 DataManager 那么我們就需要有一個 AppModule 的實例蝶怔,實現(xiàn)起來也是一套
- create 創(chuàng)建自己然后 module 傳入
- module 作為 AppModule_ProvideManagerFactory 參數(shù)在構(gòu)造賦值
- 調(diào)用 get 實際就是調(diào)用 AppModule.provideManager
然后再看 MainActivity_MembersInjector 這個類,需要實現(xiàn) MembersInjector<T> 接口
public interface MembersInjector<T> {
void injectMembers(T t);
}
public class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<DataManager> dataManagerProvider;
public MainActivity_MembersInjector(Provider<DataManager> dataManagerProvider) {
assert dataManagerProvider != null;
this.dataManagerProvider = dataManagerProvider;
}
public static MembersInjector<MainActivity> create(Provider<DataManager> dataManagerProvider){
return new MainActivity_MembersInjector(dataManagerProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if(instance == null){
throw new NullPointerException("空指針");
}
instance.dataManager = dataManagerProvider.get();
}
public static void injectDataManager(
MainActivity instance, Provider<DataManager> dataManagerProvider
){
instance.dataManager = dataManagerProvider.get();
}
}
這里 create 需要傳入 Provider<DataManager> 的 dataManagerProvider 提供 DataManger 五督,調(diào)用 dataManagerProvider.get 方法就可以得到 DataManager 的實例讓然后在 injectDataManager 方法中將這個實例賦值給 MainActivity的dataManager 屬性來完成注入概荷。所以這個類需要一個 Provider<DataManager> 實例這是在構(gòu)造函數(shù)傳入的 create 的方式與上面的 AppModule_ProvideManagerFactory 的 create 套路相同,injectMembers(MainActivity instance) 是將 MainActivity 導入進入继薛,然后我們就可以輕松地將 provider 提供 DataManager 實例賦給 MainActivity 的屬性遏考。
3. 這里調(diào)用 inject方法是 ScAppComponent的 inject 方法 也就是
mainActivityMembersInjector 的 injectMembers 方法來將 MainActivity 傳入到類供注入
ScAppComponent.builder()
.appMoudle(new AppModule())
.build() //使用構(gòu)建者模式創(chuàng)建一個 Component 實例
.inject(this);
運行代碼
: DataManager: ininial