<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] 推薦兩篇Dagger2學習教程:[《Dagger2 入門,以初學者角度》](https://www.jianshu.com/p/1d84ba23f4d2)和[《Android:dagger2讓你愛不釋手-基礎依賴注入框架篇》](https://www.jianshu.com/p/cd2c1c9f68d4) # 學習總結 ## 總覽 1、Java 中萬物皆對象,每一個對象可以擁有很多成員變量,這些成員變量可以是各種對象 2、依賴注入,顧名思義指一個類所依賴的對象的注入過程,省去了手動去為一個對象 new 一堆依賴的過程 3、Module 是依賴提供方,Activity、Fragment 等是依賴需求方,Component 是依賴注入器 4、Component 是一個接口,編譯代碼后,會自動生成一個實現類 ## 工作流程 1、調用 Component 實現類的 inject 方法,把依賴需求方對象(比如 Activity 自身),傳遞給 Component 2、Component 根據依賴需求方的需求,從 Module 中尋找現成的實例對象,并注入給依賴需求方(Activity) ## 關鍵注解說明 ### @Component 一個標注的 @Component 注解形式如下: ```java @Component(dependencies = AppComponent.class,modules = {MainModule.class, ActivityModule.class}) public interface MainComponent extends ActivityComponent{ ... } ``` @Component 注解有兩個屬性:dependencies 和 modules。dependencies 屬性聲明 @Component 的依賴關系,modules 屬性聲明 @Component 后期會從哪些 @Module 中去尋找依賴實例。 我們在 創建 @Component 的實現類對象時,需要提供父 Component 實例對象和 Module 實例對象,如下: ```java mMainComponent = DaggerMainComponent.builder().appComponent(getAppComponent()) .mainModule(new MainModule()) .activityModule(new ActivityModule(this)).build(); mMainComponent.inject(this); ``` ### @Scope Scope 的意思是“范圍”,即用來聲明依賴對象作用范圍的 > Dagger2 有一個機制:在同一個作用范圍內,@Provides 方法提供的依賴對象會變成單例。即依賴需求方不管依賴幾次 @Provides 提供的對象,Dagger2 都會只調用一次該 @Provides 方法來獲取依賴實例,后期再需要該依賴實例時直接進行提供。 @Scope 注解需要自定義注解才可以使用,@Singleton 就是一個自定義注解: ```java @Scope @Documented @Retention(RUNTIME) public @interface Singleton {} ``` 依賴提供方 Module 的 @Provides 方法使用 @Singleton 注解聲明,依賴注入器 Component 也使用 @Singleton 注解聲明即可。這樣 Module 提供的依賴對象就是單例的了。 ### @Qulifier Dagger2 是通過返回值類型來從 Module 中獲取依賴對象的。也就是說像如下的 Module 代碼中,Component 并不知道該調用哪一個方法來生成對象: ```java @Provides public Cloth getRedCloth() { Cloth cloth = new Cloth(); cloth.setColor("紅色"); return cloth; } @Provides public Cloth getBlueCloth() { Cloth cloth = new Cloth(); cloth.setColor("藍色"); return cloth; } ``` 所以需要一個 Qulifier 注解來進行區分: ```java @Qualifier @Retention(RetentionPolicy.RUNTIME) public @interface RedCloth { } @Qualifier @Retention(RetentionPolicy.RUNTIME) public @interface BlueCloth { } ``` 使用 @RedCloth 和 @BlueCloth 對依賴需求方和依賴提供方進行注解,便可進行區分 # 源碼分析 ## 注解 Dagger2 的工作主要是通過注解來實現的,所以理解注解至關重要,這里推薦一篇講解注解很清晰的文章:[秒懂,Java 注解 (Annotation)你可以這樣學](https://blog.csdn.net/briblue/article/details/73824058) ## 注解處理器 和 EventBus、ButterKnife 一樣,Dagger2 也是通過注解處理器來在編譯器進行代碼生成,關于注解處理器可以參考我的另一篇博文:[EventBus 3.0 源碼分析(二)注解處理器的使用](http://xuchongyang.com/2017/07/17/EventBus-3-0-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%88%E4%BA%8C%EF%BC%89%E7%BC%96%E8%AF%91%E6%97%B6%E6%B3%A8%E8%A7%A3%E5%92%8C%E8%BF%90%E8%A1%8C%E6%97%B6%E6%B3%A8%E8%A7%A3/)。 ## 源碼分析 我們先來定義一個最簡單的 Dagger2 的使用實例: MainActivity 類如下: ```java public class MainActivity extends AppCompatActivity { @Inject public Computer mComputer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MainComponent mainComponent = DaggerMainComponent.builder() .mainModule(new MainModule()) .build(); mainComponent.inject(this); } } ``` @Module 類如下: ```java @Module public class MainModule { @Provides public Computer providesAppleComputer() { return new Computer("Apple"); } } ``` @Component 類如下: ```java @Component(modules = MainModule.class) public interface MainComponent { void inject(MainActivity activity); } ``` 然后點擊 rebuild project 進行編譯。我這邊在第一次進行代碼編譯時,并沒有如預期生成 @Component 的實現類,發現由于 Dagger2 的引入是在 子 Module 中引入的,因此在 app 模塊中注解處理器無法為我們生成代碼。只要在主模塊引入注解處理器即可: ```plain annotationProcessor 'com.google.dagger:dagger-compiler:2.15' ``` 在 MainActivity 代碼中可以看到,我們先通過 Component 的實現類的 builder 模式獲取到實例對象,再調用 inject 方法進行依賴注入。注入成功后此時 MainActivity 的成員變量就已經賦值了。 我們看看 Component 的實現類 DaggerMainComponent 的源碼: ```java public final class DaggerMainComponent implements MainComponent { private MainModule mainModule; private DaggerMainComponent(Builder builder) { initialize(builder); } public static Builder builder() { return new Builder(); } public static MainComponent create() { return new Builder().build(); } @SuppressWarnings("unchecked") private void initialize(final Builder builder) { this.mainModule = builder.mainModule; } @Override public void inject(MainActivity activity) { injectMainActivity(activity); } private MainActivity injectMainActivity(MainActivity instance) { MainActivity_MembersInjector.injectMComputer( instance, MainModule_ProvidesAppleComputerFactory.proxyProvidesAppleComputer(mainModule)); return instance; } 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) { this.mainModule = Preconditions.checkNotNull(mainModule); return this; } } } ``` 代碼精簡一下,其實也很簡單,僅僅是一個標準的 builder 模式,外加實現了 Component 接口的 inject 方法: ```java public final class DaggerMainComponent implements MainComponent { private MainModule mainModule; public static Builder builder() { return new Builder(); } // ... @Override public void inject(MainActivity activity) { injectMainActivity(activity); } public static final class Builder { // ... } } ``` 接下來我們一一看: **1、Component使用Builder模式創建Module成員變量** 首先是 builder 模式的 build 方法: ```java public MainComponent build() { if (mainModule == null) { this.mainModule = new MainModule(); } return new DaggerMainComponent(this); } ``` ```java private DaggerMainComponent(Builder builder) { initialize(builder); } ``` ```java @SuppressWarnings("unchecked") private void initialize(final Builder builder) { this.mainModule = builder.mainModule; } ``` 很好理解,其實就是給 DaggerMainComponent 的成員變量 mainModule 對象進行賦值操作。接下來看看比較關鍵的注入操作: **2、Component為待注入對象進行依賴注入** ```java @Override public void inject(MainActivity activity) { injectMainActivity(activity); } ``` ```java private MainActivity injectMainActivity(MainActivity instance) { MainActivity_MembersInjector.injectMComputer( instance, MainModule_ProvidesAppleComputerFactory.proxyProvidesAppleComputer(mainModule)); return instance; } ``` 可以看到,注入操作是調用了 MainActivity_MembersInjector 這個類的 injectMComputer 方法,看看這個方法: ```java // MainActivity_MembersInjector.java public static void injectMComputer(MainActivity instance, Computer mComputer) { instance.mComputer = mComputer; } ``` 在 injectMComputer 方法中,直接把第二個參數 Computer 對象賦值給依賴需求方 MainActivity。MainActivity 是我們直接手動傳遞過來的,那么第二個參數的依賴對象是怎么來的呢,也就是 `MainModule_ProvidesAppleComputerFactory.proxyProvidesAppleComputer(mainModule)` 這一行代碼是如何拿到一個目標依賴對象的呢? 編譯時 Dagger2 自動為我們生成了 MainModule_ProvidesAppleComputerFactory 這個類,看名稱就知道是提供 AppleComputer 的工廠類,對應著我們 MainModule 中的 providesAppleComputer。看看 proxyProvidesAppleComputer 方法: ```java // MainModule_ProvidesAppleComputerFactory.java public static Computer proxyProvidesAppleComputer(MainModule instance) { // 此處做一下非空判斷 return Preconditions.checkNotNull( instance.providesAppleComputer(), "Cannot return null from a non-@Nullable @Provides method"); } ``` 參數 MainModule 就是剛才在 builder 方法中初始化的那個 MainModule。最終返回的是 MainModule 的 providesAppleComputer 方法所提供的實例對象。至此,Component 就完成了從 Module 中獲取依賴實例對象,并注入到依賴需求方的過程。 ## 總結 1、Component的實現類采用Builder模式,完成Component成員變量Module的設置。 2、Component實現類的inject方法,參數為等待注入的對象(如Activity等),將Module提供的對象設置給等待注入的對象。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看