Dagger2的理解和使用

Android:dagger2讓你愛不釋手-基礎(chǔ)依賴注入框架篇
Android:dagger2讓你愛不釋手-重點概念講解敏晤、融合篇
Android:dagger2讓你愛不釋手-終結(jié)篇

Dagger 2 完全解析(一)嗡载,Dagger 2 的基本使用與原理
Dagger 2 完全解析(二),進階使用 Lazy麻车、Qualifier临梗、Scope 等
Dagger 2 完全解析(三)蠢沿,Component 的組織關(guān)系與 SubComponent
Dagger 2 完全解析(四)肩榕,Android 中使用 Dagger 2
Dagger 2 完全解析(五)垮抗,Kotlin 中使用 Dagger 2
Dagger 2 完全解析(六)氏捞,dagger.android 擴展庫的使用

1、Component的使用

作為橋連接依賴和被依賴對象冒版。
每一個Component都會創(chuàng)建一個對應(yīng)的DaggerComponent
@Inject注解的構(gòu)造函數(shù)會創(chuàng)建對應(yīng)類的Factory液茎,用于實例化該類

/**
 * 藥物
 */

public class Medicine {

    @Inject
    public Medicine() {
    }

    public void treat() {
        LogUtil.e("開始治療");
    }
}
/**
 * 注射器
 */

@Component
public interface Injector {
    //注射動作,指定病患
    void inject(MainActivity mainActivity);
}
/**
 * 病患
 */
public class MainActivity extends AppCompatActivity {

    @Inject
    Medicine mMedicine;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //口服
        Medicine medicine = new Medicine();
        medicine.treat();
        //打針
        DaggerInjector.create().inject(this);
        mMedicine.treat();
    }
}  

2辞嗡、Module使用場景

1捆等、沒有構(gòu)造函數(shù)
2、有參構(gòu)造
3续室、三方庫的類
每一個@Provides注解的方法都會創(chuàng)建一個Factory用來提供實例化對象給DaggerComponent使用栋烤。
@Provides注解的方法所需要的參數(shù)會優(yōu)先從Module的其他provide中取。

@Module
public class ModuleClass {

    @Provides
    Gson provideGson() {
        return new Gson();
    }
}
@Component(modules = ModuleClass.class)
public interface ComponentClass {
    void inject(MainActivity2 mainActivity);
}
public class MainActivity2 extends AppCompatActivity {

    @Inject
    Gson mGson;

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

        DaggerComponentClass.create().inject(this);
        String s = mGson.toJson(new Medicine());
        LogUtil.e(s);
    }
}

3挺狰、@Scope作用域

@Scope是一個元注解明郭,用于注解自定義注解买窟,可以確定注入的實例的生命周期,并在聲明周期內(nèi)保持實例唯一达址。使用時Module 中 provide 方法中的 Scope 注解必須和 與之綁定的 Component 的 Scope 注解必須一樣蔑祟,否則作用域不同會導(dǎo)致編譯時會報錯。
作用域的原理沉唠,其實是讓生成的依賴實例的生命周期與 Component 綁定疆虚,Scope 注解并不能保證生命周期,要想保證賴實例的生命周期满葛,需要確保 Component 的生命周期径簿。

@Singleton是通過@Scope定義的一個新的注解,能夠使同一個Component中的對象保持唯一嘀韧,保持唯一的條件是通過@Scope標(biāo)記的注解相同篇亭。

@Singleton并沒有創(chuàng)建單例的能力,起作用為
1锄贷、保證Component和Module是匹配的译蒂。
2、代碼可讀性谊却。

以頁面劃分component柔昼,一個頁面一個component,但這并不是一定的炎辨,有時候多頁面會共用一個component捕透,因為它們需要的參數(shù)一致。

一個全局component用來管理管理整個App的全局類實例碴萧。

@Scope //注明是Scope 
@Documented  //標(biāo)記在文檔 
@Retention(RUNTIME)  // 運行時級別
public @interface Singleton {}
@Module
public class FactoryModule {

    @Provides
    Gson provideGson() {
        LogUtil.e("創(chuàng)建Gson對象");
        return new Gson();
    }

}
@Component(modules = FactoryModule.class)
public interface BridgeComponent {
    Gson getGson();
}
public class App extends Application {

    public static BridgeComponent sBridgeComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        sBridgeComponent = DaggerBridgeComponent.create();
    }

}
@Module
public class ActivityModule {

    @Singleton
    @Provides
    Person5 providesPersonWithString() {
        return new Person5("xls");
    }

}
@Singleton
@Component(dependencies = BridgeComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
    void inject(MainActivity3 mainActivity);
}
public class MainActivity3 extends AppCompatActivity {

    @Inject
    Person5 mPerson5;

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

        DaggerActivityComponent.builder().bridgeComponent(App.sBridgeComponent).activityModule(new ActivityModule()).build().inject(this);
        Gson gson = App.sBridgeComponent.getGson();
        LogUtil.e(gson.toJson(mPerson5));
    }
}

4乙嘀、有參構(gòu)造

MainModule -->providesPerson()中new Person(context)不能直接使用this.context,Module中查找返回Context的方法破喻,并注入虎谢。此場景默認(rèn)調(diào)用providesContext方法獲取context。

public class Person {

    public String name = "張三";
    public int age = 23;

    private Context context;

    public Person(Context context) {
        LogUtil.e("a person created with context:" + context);
    }
}
@Module
public class MainModule {

    private Context context;

    public MainModule(Context context) {
        this.context = context;
    }

    @Provides
    public Context providesContext() {
        return this.context;
    }

    @Provides
    public Person providesPerson(Context context) {
        LogUtil.e("person from module");
        return new Person(context);
    }
}
@Component(modules = MainModule.class)
public interface MainComponent {
    void inject(MainActivity4 mainActivity4);
}
public class MainActivity4 extends AppCompatActivity {

    @Inject
    Person mPerson;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainComponent.builder().mainModule(new MainModule(getApplicationContext())).build().inject(this);
        String s = App.getInstance().mGson.toJson(mPerson);
        LogUtil.e(s);
    }
}

5曹质、自定義標(biāo)記婴噩、限定符

用于區(qū)分同類的不同依賴

public class Person5 {

    public String name = "張三";
    public int age = 23;
    public Context context;

    public Person5(Context context) {
        this.context = context;
        LogUtil.e("a person created with context:" + context);
    }

    public Person5(String name) {
        this.name = name;
        LogUtil.e("a person created with name:" + name);
    }
}
@Module
public class MainModule5 {
    private Context context;

    public MainModule5(Context context) {
        this.context = context;
    }

    @Provides
    public Context providesContext() {
        return this.context;
    }

    //    @Named("context")
    @PersonForContext
    @Provides
    public Person5 providesPersonWithContext(Context context) {
        return new Person5(context);
    }

    //    @Named("string")
    @PersonForName
    @Provides
    public Person5 providesPersonWithName() {
        return new Person5("yxm");
    }

}
@Component(modules = MainModule5.class)
public interface MainComponent5 {
    void inject(MainActivity5 mainActivity5);
}
public class MainActivity5 extends AppCompatActivity {

    //    @Named("string")
    @PersonForName
    @Inject
    Person5 p1;

    //    @Named("context")
    @PersonForContext
    @Inject
    Person5 p2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainComponent5.builder().mainModule5(new MainModule5(getApplicationContext())).build().inject(this);
        String s1 = App.getInstance().mGson.toJson(p1);
        LogUtil.e(s1);
        //java.lang.SecurityException: Can not make a java.lang.reflect.Method constructor accessible
//        String s2 = App.getInstance().mGson.toJson(p2);
//        LogUtil.e(s2);
    }
}
@Qualifier  // 關(guān)鍵詞
@Retention(RetentionPolicy.RUNTIME)  // 運行時仍可用
public @interface PersonForContext {
    // Context 對象的注解
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonForName {
    // name 對象的注解
}

6、Provider咆繁、Lazy

沿用demo5部分文件

@Module
public class MainModule5 {
    private Context context;

    public MainModule5(Context context) {
        this.context = context;
    }

    @Provides
    public Context providesContext() {
        return this.context;
    }

    //    @Named("context")
    @PersonForContext
    @Provides
    public Person5 providesPersonWithContext(Context context) {
        return new Person5(context);
    }

    //    @Named("string")
    @PersonForName
    @Singleton
    @Provides
    public Person5 providesPersonWithName() {
        return new Person5("yxm");
    }

}
@Singleton
@Component(modules = MainModule5.class)
public interface MainComponent5 {
    void inject(MainActivity5 mainActivity5);
}

public class MainActivity5 extends AppCompatActivity {

    //    @Named("string")
    @PersonForName
    @Inject
    Person5 p1;

    @PersonForName
    @Inject
    Provider<Person5> providerPerson;

    //    @Named("context")
    @PersonForContext
    @Inject
    Lazy<Person5> lazyPerson;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerMainComponent5.builder().mainModule5(new MainModule5(getApplicationContext())).build().inject(this);
        Person5 person5 = lazyPerson.get();// 調(diào)用該方法時才會去創(chuàng)建Person,以后每次調(diào)用獲取的是同一個對象
        Person5 person6 = lazyPerson.get();
        Person5 person7 = providerPerson.get();// 調(diào)用該方法時才回去創(chuàng)建Person1,以后每次調(diào)用都會重新加載Module中的具體方法顶籽,根據(jù)Module中的實現(xiàn)玩般,可能相同,可能不相同礼饱。加@Singletom注解坏为,創(chuàng)建一次
        Person5 person8 = providerPerson.get();

        String s1 = App.getInstance().mGson.toJson(p1);
        LogUtil.e(s1);
        //java.lang.SecurityException: Can not make a java.lang.reflect.Method constructor accessible
//        String s2 = App.getInstance().mGson.toJson(p2);
//        LogUtil.e(s2);
    }
}

總結(jié)

1究驴、將實例化操作抽離出來,達到解耦的效果
2匀伏、單例無需考慮線程是否安全

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洒忧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子够颠,更是在濱河造成了極大的恐慌熙侍,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件履磨,死亡現(xiàn)場離奇詭異蛉抓,居然都是意外死亡,警方通過查閱死者的電腦和手機剃诅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門巷送,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人矛辕,你說我怎么就攤上這事×钠罚” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵杨刨,是天一觀的道長。 經(jīng)常有香客問我妖胀,道長芥颈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任赚抡,我火速辦了婚禮爬坑,結(jié)果婚禮上涂臣,老公的妹妹穿的比我還像新娘盾计。我一直安慰自己,他們只是感情好赁遗,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布署辉。 她就那樣靜靜地躺著,像睡著了一般岩四。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上材鹦,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音桶唐,去河邊找鬼。 笑死尤泽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的安吁。 我是一名探鬼主播醉蚁,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼网棍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了滥玷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤惑畴,失蹤者是張志新(化名)和其女友劉穎航徙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體到踏,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年楣富,在試婚紗的時候發(fā)現(xiàn)自己被綠了伴榔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纹蝴。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡踪少,死狀恐怖塘安,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情援奢,我是刑警寧澤兼犯,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布免都,位于F島的核電站,受9級特大地震影響绕娘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜险领,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一秒紧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧熔恢,春花似錦、人聲如沸叙淌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至茂洒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渠羞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工堵未, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盏触,地道東北人渗蟹。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓雌芽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親世落。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348