天天看點

Dagger2全面解析

      • Dagger2的好處
      • 相關标簽
      • 标簽使用方式
      • 注入方式
      • 不同類的關系
      • 編譯後的生成檔案與原檔案及關系圖
      • 注入路徑
      • Scope用于劃分作用域
        • 各标簽的意義
      • Singleton的單例模式是如何起作用的我隻是個栗子
      • Qualifier的巧用指哪打哪

Dagger2的好處

  • 依賴的注入和配置獨立于元件之外。
  • 因為對象是在一個獨立、不耦合的地方初始化,是以當注入抽象方法的時候,我們隻需要修改對象的實作方法,而不用大改代碼庫。
  • 依賴可以注入到一個元件中:我們可以注入這些依賴的模拟實作,這樣使得測試更加簡單。

相關标簽

@Inject、@Module、@Provide、@Component

  • @Inject: 通常在需要依賴的地方使用這個注解。換句話說,你用它告訴Dagger這個類或者字段需要依賴注入。這樣,Dagger就會構造一個這個類的執行個體并滿足他們的依賴。
  • @Module: Modules類裡面的方法專門提供依賴,是以我們定義一個類,用@Module注解,這樣Dagger在構造類的執行個體的時候,就知道從哪裡去找到需要的依賴。modules的一個重要特征是它們設計為分區并組合在一起(比如說,在我們的app中可以有多個組成在一起的modules)。
  • @Provide: 在modules中,我們定義的方法是用這個注解,以此來告訴Dagger我們想要構造對象并提供這些依賴。
  • @Component: Components從根本上來說就是一個注入器,也可以說是@Inject和@Module的橋梁,它的主要作用就是連接配接這兩個部分。 Components可以提供所有定義了的類型的執行個體,比如:我們必須用@Component注解一個接口然後列出所有的@Modules組成該元件,如果缺失了任何一塊都會在編譯的時候報錯。所有的元件都可以通過它的modules知道依賴的範圍。

标簽使用方式

[email protected]

public class User {  

    ....  
    ....  
    //在被依賴類中使用@Inject标記該類的構造方法
    @Inject  
    public User() {  
    }  

    ....  
    ....    
}  
           
public class MainActivity extends AppCompatActivity {  

    //在依賴類中使用@Inject來注入被依賴類執行個體
    @Inject  
    User user;  
    @Inject  
    User user2;  
    private TextView tv;  
    private TextView tv2;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        //執行個體component,并通過其inject()方法來對成員變量(通過@Inject進行表述的)進行指派
        DaggerActivityComponent.builder().build().inject(this);  
        tv = ((TextView) findViewById(R.id.tv));  
        tv2 = ((TextView) findViewById(R.id.tv2));  
        tv.setText(user.toString());  
        tv2.setText(user2.toString());  
    }  
} 
           

[email protected]

@Component  
public interface ActivityComponent {  
    void inject(MainActivity activity);  
}  
           

[email protected] & @Module

@Module  
public class UserModule {  
    @Provides
    User providesUser() {  
        return new User();  
    }  
}  
           

注入方式

  • 構造方法注入:在類的構造方法前面注釋@Inject
  • 成員變量注入:在類的成員變量(非私有)前面注釋@Inject
  • 函數方法注入:在函數前面注釋@Inject

不同類的關系

Dagger2全面解析

編譯後的生成檔案與原檔案及關系圖

原檔案

Dagger2全面解析

生成檔案

Dagger2全面解析

各檔案對應關系

Dagger2全面解析

注入路徑

Dagger2全面解析
Dagger2全面解析
Dagger2全面解析

@Scope(用于劃分作用域)

javax包中自帶的@Singleton,其class如下:

Dagger2全面解析

使用者自己寫的

Dagger2全面解析

可以看出除了少了@Documented标簽外,使用者自己寫的Scope标簽和@Singleton并沒有本質的差別

各标簽的意義

@Retention

Retention(保留)注解說明,這種類型的注解會被保留到那個階段. 有三個值:

1.RetentionPolicy.SOURCE —— 這種類型的Annotations隻在源代碼級别保留,編譯時就會被忽略

2.RetentionPolicy.CLASS —— 這種類型的Annotations編譯時被保留,在class檔案中存在,但JVM将會忽略

3.RetentionPolicy.RUNTIME —— 這種類型的Annotations将被JVM保留,是以他們能在運作時被JVM或其他使用反射機制的代碼所讀取和使用.

@Documented

Documented 注解表明這個注解應該被 javadoc工具記錄. 預設情況下,javadoc是不包括注解的. 但如果聲明注解時指定了 @Documented,則它會被 javadoc 之類的工具處理, 是以注解類型資訊也會被包括在生成的文檔中. 示例6進一步示範了使用

@Scope

Dagger2全面解析

@Singleton的單例模式是如何起作用的(我隻是個栗子)

該單例模式的前提是所使用的Component執行個體是同一個的情況下,而且任何自定義的Scope标簽都有相同功能,具體實作如下:

Dagger2全面解析
Dagger2全面解析

@Qualifier的巧用(指哪打哪)

@Qualifier是用來給注解做注解的。它告訴Dagger依賴需求方 建立資料的時候使用哪個依賴提供方。

兩個@Qualifier

@Qualifier
public @interface ThemeNight {

}

@Qualifier
public @interface ThemeDay {
}
           
@Module
public class ThemeModule {
    @Provides
    @ThemeDay
    Theme provideDayTheme() {
        return new Theme("day");
    }

    @Provides
    @ThemeNight
    Theme provideNightTheme() {
        return new Theme("night");
    }
}
           
@Component
public interface ThemeComponent{
    void inject(ThemeTest themeTest);
}
           
public class ThemeTest {
    @Inject
    @ThemeDay
    Theme dayTheme;
    @Inject
    @ThemeNight
    Theme nightTheme;

    public static void main(String[] arg) {
        ThemeTest themeTest = new ThemeTest();
        DaggerThemeComponent.create().inject(themeTest);
        System.out.println(themeTest.dayTheme.themeName);
        System.out.println(themeTest.nightTheme.themeName);
    }
}
           

繼續閱讀