Dagger2 學(xué)習(xí)與理解

Dagger2 使用編譯時(shí)注解 + APT 實(shí)現(xiàn)依賴注入,能帶來什么好處呢?一個(gè)詞:解耦。在項(xiàng)目越來越龐大的時(shí)候,Dagger2 就體現(xiàn)出強(qiáng)大之處了。

編譯時(shí)注解 + APT 實(shí)現(xiàn)的框架,通過解析注解,然后生成輔助類。But,是沒用到反射的。都是在編譯時(shí)完成。要分析 Dagger2 的工作原理,那么就要去探索生成的輔助類。
一個(gè)簡單的例子,往 MainActivity 注入 MainPresenter 依賴(ps:MVP + Dagger2 簡直不能太般配):

public class MainActivity extends AppCompatActivity {

    public static final String TAG = MainActivity.class.getSimpleName();

    @Inject
    MainPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        injectDependences();
        Log.d(TAG,"MainPresenter ->" + presenter.hashCode());
    }

    private void injectDependences(){
        DaggerMainComponent.builder()
                .mainModule(new MainModule())
                .build()
                .inject(this);
    }

}

@Component(modules = {MainModule.class})
public interface MainComponent {

    void inject(MainActivity mainActivity);

}

@Module
public class MainModule {

    @Provides MainPresenter provideMainPresenter(){
        return new MainPresenter();
    }
}

public class MainPresenter {

}

以上代碼直接貼了,很簡單。接下來我們分析在編譯時(shí)生成的類。這些類存放在在 app/build/generated/source/apt/debug/包名
DaggerMainComponent 源碼如下所示:

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerMainComponent implements MainComponent {
 private Provider<MainPresenter> provideMainPresenterProvider;
 private MembersInjector<MainActivity> mainActivityMembersInjector;

 private DaggerMainComponent(Builder builder) {  
   assert builder != null;
   initialize(builder);
 }

 public static Builder builder() {  
   return new Builder();
 }

 public static MainComponent create() {  
   return builder().build();
 }

 private void initialize(final Builder builder) {  
   this.provideMainPresenterProvider = MainModule_ProvideMainPresenterFactory.create(builder.mainModule);
   this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideMainPresenterProvider);
 }


 //inject 方法實(shí)現(xiàn)依賴注入
 @Override
 public void inject(MainActivity mainActivity) {  
   mainActivityMembersInjector.injectMembers(mainActivity);
 }

 public static final class Builder {
   private MainModule mainModule;

   private Builder() {  
   }

   public MainComponent build() {  
     if (mainModule == null) {
       this.mainModule = new MainModule();
     }
     return new DaggerMainComponent(this);
   }

   public Builder mainModule(MainModule mainModule) {  
     if (mainModule == null) {
       throw new NullPointerException("mainModule");
     }
     this.mainModule = mainModule;
     return this;
   }
 }
}

DaggerMainComponent 是使用建造者模式創(chuàng)建的,那么先看到其內(nèi)部的 Builder 類,Builder 類有一個(gè) mainModule 方法,傳入 MainModule 對象,如果 MainModule 為空會(huì)拋出空指針異常,最后 mainModule 方法返回了 this。

然后調(diào)用 build 方法。在 build 方法中創(chuàng)建一個(gè) DaggerMainComponent 并返回,此時(shí)只需要關(guān)注 DaggerMainComponent 的構(gòu)造方法即可。

在 DaggerMainComponent 的構(gòu)造方法中,將 Builder 對象傳入 initialize 方法,initialize 方法雖然只有兩行代碼,但這兩行代碼很關(guān)鍵。我們看到這個(gè) initialize 方法做了兩件事。

調(diào)用了 MainModule_ProvideMainPresenterFactory 類的靜態(tài)方法 create,并將 MainModule 對象傳入,返回了一個(gè) Provider 對象。 這里的 MainModule 對象來自 Builder 對象。是在初始化 DaggerMainComponent 的時(shí)候創(chuàng)建的。

調(diào)用 MainActivity_MembersInjector 的 create,并將 Provider 對象傳進(jìn)。返回一個(gè) MembersInjector 對象。

到這里,只需要記住。Apt 在編譯時(shí)為我們生成了三個(gè)類
DaggerMainComponent
MainModule_ProvideMainPresenterFactory
MainActivity_MembersInjector

雖然名字很長,但是認(rèn)真看幾遍的話,很還記的。
以上是 DaggerMainComponent 類,
還需要繼續(xù)挖掘 MainModule_ProvideMainPresenterFactory 和 MainActivity_MembersInjector。

MainModule_ProvideMainPresenterFactory 源碼如下:

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class MainModule_ProvideMainPresenterFactory implements Factory<MainPresenter> {
  private final MainModule module;

  public MainModule_ProvideMainPresenterFactory(MainModule module) {  
    assert module != null;
    this.module = module;
  }

  @Override
  public MainPresenter get() {  
    MainPresenter provided = module.provideMainPresenter();
    if (provided == null) {
      throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
    }
    return provided;
  }

  public static Factory<MainPresenter> create(MainModule module) {  
    return new MainModule_ProvideMainPresenterFactory(module);
  }
}

我們在 DaggerMainComponent 中調(diào)用了 MainModule_ProvideMainPresenterFactory 類的靜態(tài)方法 create。那么從調(diào)用入口開始分析,找到 create 方法。create 方法內(nèi)部 new 了一個(gè) MainModule_ProvideMainPresenterFactory 對象。注意到還有一個(gè) get 方法,但是我們現(xiàn)在還不知道在哪里調(diào)用了這個(gè) get 方法。先記下。
MainActivity_MembersInjector 源碼如下:

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final MembersInjector<AppCompatActivity> supertypeInjector;
  private final Provider<MainPresenter> presenterProvider;

  public MainActivity_MembersInjector(MembersInjector<AppCompatActivity> supertypeInjector, Provider<MainPresenter> presenterProvider) {  
    assert supertypeInjector != null;
    this.supertypeInjector = supertypeInjector;
    assert presenterProvider != null;
    this.presenterProvider = presenterProvider;
  }

  @Override
  public void injectMembers(MainActivity instance) {  
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    supertypeInjector.injectMembers(instance);
    instance.presenter = presenterProvider.get();
  }

  public static MembersInjector<MainActivity> create(MembersInjector<AppCompatActivity> supertypeInjector, Provider<MainPresenter> presenterProvider) {  
      return new MainActivity_MembersInjector(supertypeInjector, presenterProvider);
  }
}

同樣是從調(diào)用入口 create 方法開始。生成 MainActivity_MembersInjector 對象。
到這里為止,初始化工作全部完成。
現(xiàn)在想一下 MainPresenter 是怎樣注入到 MainActivity 的呢?

DaggerMainComponent.builder() .mainModule(new MainModule()) .build() .inject(this);

很容易猜想到是 DaggerMainComponent 的 inject 方法。
我們回到 DaggerMainComponent 從入口 inject 方法開始, inject 方法傳進(jìn)了MainActivity。然后調(diào)用了 MainActivityMembersInjector 對象的 injectMembers 方法,如下所示:

@Override
public void injectMembers(MainActivity instance) {  
  if (instance == null) {
    throw new NullPointerException("Cannot inject members into a null reference");
  }
  supertypeInjector.injectMembers(instance);
  instance.presenter = presenterProvider.get();
}

而在 injectMembers 方法,終于可以看到調(diào)用 get 方法的代碼

instance.presenter = presenterProvider.get();

就這樣完成了依賴注入,instance 是 MainActivity,而 presenter 是需要注入的 MainPresenter 對象。
那么現(xiàn)在只需要關(guān)注 presenterProvider 的 get 方法即可。presenterProvider 是什么? 是 MainModule_ProvideMainPresenterFactory 對象,在創(chuàng)建 MainActivity_MembersInjector 的時(shí)候傳入的。
找到 MainModule_ProvideMainPresenterFactory 的 get 方法。如下所示:

@Override
public MainPresenter get() {  
  MainPresenter provided = module.provideMainPresenter();
  if (provided == null) {
    throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
  }
  return provided;
}

其內(nèi)部是調(diào)用了 MainModule 對象的工廠方法 provideMainPresenter 方法來生成 MainPresenter 對象。如下:

@Module
public class MainModule {

    @Provides MainPresenter provideMainPresenter(){
        return new MainPresenter();
    }
}

分析完畢!
總結(jié)
DaggerMainComponent 在創(chuàng)建的時(shí)候,需要傳入 Module,這個(gè)傳入的 Module 到底用來干嘛的? Factory 的 get 方法中會(huì)調(diào)用 Mudule 的工廠方法獲取到依賴。

DaggerMainComponent 在創(chuàng)建的時(shí)候,還創(chuàng)建了 Factory(工廠類,對應(yīng)上文的 MainModule_ProvideMainPresenterFactory) 和MembersInjector(成員注入類,對應(yīng)上文的 MainActivity_MembersInjector) 。

當(dāng) DaggerMainComponent 調(diào)用 inject 方法注入依賴的時(shí)候,會(huì)調(diào)用 MembersInjector 的 injectMembers 方法,在 injectMembers 方法中會(huì)調(diào)用Factory 的 get 方法獲取到依賴(get 方法中實(shí)際會(huì)調(diào)用 Mudule 的工廠方法獲取到依賴),最后將依賴賦值給 目標(biāo)類 的成員變量。完成依賴注入。

最后,你會(huì)發(fā)現(xiàn)這篇文章沒有使用到 @Qulifier, @Scope(我覺的@Scope注解不好理解)。而且Module類也只有一個(gè)方法,如果有多個(gè)方法呢?生成的輔助類又會(huì)如何?
學(xué)習(xí)資料
https://google.github.io/dagger/
神兵利器Dagger2
Android:dagger2讓你愛不釋手-基礎(chǔ)依賴注入框架篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容