Dagger2進(jìn)階使用

1 知識(shí)回顧

先來回顧之前將的四個(gè)注解

  • @Inject:
    通常在需要依賴的地方使用這個(gè)注解途乃。換句話說,你用它告訴Dagger這個(gè)類或者字段需要依賴注入。這樣,Dagger就會(huì)構(gòu)造一個(gè)這個(gè)類的實(shí)例并滿足他們的依賴。
  • @Module:
    Modules類里面的方法專門提供依賴,所以我們定義一個(gè)類,用@Module注解,這樣Dagger在構(gòu)造類的實(shí)例時(shí)候侦鹏,就知道從哪里去找到需要的依賴。
  • @Provide:
    在Modules中臀叙,我們定義的方法用這個(gè)注解略水,以此來告訴Dagger我們想要構(gòu)造對(duì)象并提供這些依賴。
  • @Component
    Components從根本上來說就是一個(gè)注入器匹耕,也可以說是@Inject和@Module的橋梁聚请,它的主要作用就是連接這兩個(gè)部分。Components可以提供所有定義了的類型的實(shí)例稳其。

2 模塊化

就好比平時(shí)我們都需要對(duì)Http請(qǐng)求進(jìn)行封裝驶赏,在Dagger里呢,我們就要對(duì)Http進(jìn)行模塊化既鞠。 這里就舉個(gè)例子煤傍,我們使用Retrofit網(wǎng)絡(luò)請(qǐng)求框架,去請(qǐng)求天氣Json數(shù)據(jù)嘱蛋。

我們先去寫一個(gè)HttpModule

//HttpModule.java
@Module
public class HttpModule {
    @Singleton
    @Provides
    public OkHttpClient getOkHttpClient() {
        Log.i("http", "getOkHttpClient");
        return new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build();
    }
    @Provides
    @Singleton
    public Retrofit getRetrofit(OkHttpClient okHttpClient) {
        Log.i("http", "getRetrofit");
        return new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create()).baseUrl("http://www.weather.com.cn/data/sk/").client(okHttpClient).          addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
    }
}
//HttpApi.java
public interface HttpApi {
    //http://www.weather.com.cn/data/sk/101010100.html
    @GET("101010100.html")
    Call<WeatherBean> getweather();
}

有人肯定會(huì)問 @Singleton是什么意思蚯姆,這個(gè)注釋表示單例使用的意思。為什么我們要進(jìn)行實(shí)例化呢洒敏?因?yàn)槲覀兠看尉W(wǎng)絡(luò)請(qǐng)求都要對(duì)OkHttpClient和Retrofit進(jìn)行實(shí)例化龄恋,這樣會(huì)造成資源的浪費(fèi),可以使單例模式下這是問程序的一種優(yōu)化吧凶伙。 @Singleton的使用后面會(huì)講郭毕。
接著我們來看看Component的代碼

@Singleton
@Component(modules = HttpModule.class)
public interface ApplicationComponent {
    void inject(MainActivity mainActivity);
}

再來看看MainActivity中使用Dagger2

public class MainActivity extends AppCompatActivity {
    String TAG = "MainActivity";
    TextView textView;
    @Inject
    Retrofit retrofit;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.tv);
        DaggerApplicationComponent.create().inject(this);
        retrofit.create(HttpApi.class).getweather().enqueue(new Callback<WeatherBean>() {
            @Override
            public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
                Log.i("http", response.isSuccessful() + "" + response.body().getWeatherinfo().getCity());
                textView.setText(response.body().getWeatherinfo().getCity());
            }
            @Override
            public void onFailure(Call<WeatherBean> call, Throwable t) {
            }
        });
    }
}

3 Singleton 單例講解

現(xiàn)在我們來講解一下@Singleton 注解的使用的注意事項(xiàng)。

  1. module 的 provide 方法使用了 Singleton 函荣,那么 component 就必須使用同一個(gè)注解
  2. Singleton 的生命周期依附于component显押,同一個(gè)module provide singleton ,不同component 也是不一樣

第一點(diǎn)也就是為什么我要在ApplicationComponent中去使用Singleton注解
第二點(diǎn)大家可以自行去嘗試。

4 升級(jí)用法

但是會(huì)有一個(gè)問題傻挂,如果我按照上面的這種方法去使用Http請(qǐng)求乘碑,還用上了單例模式,然而卻體現(xiàn)不出單例模式的好處金拒,按照上面的做法兽肤,我每個(gè)Activity使用 @Inject Retrofit retrofit;這個(gè)注解相對(duì)應(yīng)的,我要對(duì)每個(gè)Activity創(chuàng)建對(duì)應(yīng)的comoponent,這和單例有什么關(guān)系呢轿衔?
所以我們要在上述代碼上進(jìn)行修改沉迹,進(jìn)行改進(jìn)。我們需要將HttpModule 使用的對(duì)象提高一個(gè)檔次害驹,不是面向Activity這個(gè)級(jí)別而是面向Application這個(gè)級(jí)別。Application和Activity顯然不是一個(gè)級(jí)別蛤育,通過Application再結(jié)合單例模式宛官,這才是HttpModule真正使用的用處。
為此我們先來修改ApplicationComponent

@Singleton
@Component(modules = HttpModule.class)
public interface ApplicationComponent {
}

看到這個(gè)大家可能會(huì)有疑問瓦糕,為什么不是像上面那樣
void inject(Application application);?
因?yàn)槿绻覀円褂?void inject(MainActivity mainActivity)的話底洗,表示Component將該module和MainActivity 連接,若要和Application連接不需要寫咕娄。
然后我們就需要在Application中聲明亥揖。

public class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
         DaggerApplicationComponent.create();
    }
}

這樣就完成將Httpmodule和Application連接。
接下來我們還需要寫一個(gè)Module類去返回HttpApi

@Module
public class ApiModule {
    @Provides
    HttpApi provideHttpapi(Retrofit retrofit) {
        return retrofit.create(HttpApi.class);
    }
}

但是Retrofit 這個(gè)對(duì)象在HttpModule中有返回圣勒,可是HttpModule已經(jīng)和Application有連接了和ApiModule 沒有任何關(guān)系费变。但是沒關(guān)系,我們可以通過component去依賴(換句話說去繼承可能會(huì)更好理解)

@Component(modules = ApiModule.class, dependencies = ApplicationComponent.class)
public interface HttpCompotent {
    void getactivity(MainActivity mainActivity);
}

然后在ApplicationComponent中加入一句話

@Singleton
@Component(modules = HttpModule.class)
public interface ApplicationComponent {
    Retrofit retrofit();
}

添加這句話的目的是為了然會(huì)返回Retrofit 圣贸,以至于讓ApiModule 的provideHttpapi方法能過找到Retrofit 挚歧。
這個(gè)時(shí)候我們 Rebuild Project一下,很好報(bào)錯(cuò)了吁峻,這是為什么呢滑负?下面我再告訴你們一些注意事項(xiàng)

  1. 沒有@scope的component不能依賴有@scope的component
  2. component的dependencies與component自身的@scope不能相同,即組件之間的@scope不同

對(duì)于突然看到@scope一定很眼生用含,@scope就是作用域的意思@Singleton是里面的一種矮慕。


參照上面兩點(diǎn)注意事項(xiàng)我們來修改HttpCompotent

@Applicaton_Annotation
@Component(modules = ApiModule.class, dependencies = ApplicationComponent.class)
public interface HttpCompotent {
    void getactivity(MainActivity mainActivity);
}

//Applicaton_Annotation .java
@Scope
@Documented
@Retention(RUNTIME)
public @interface Applicaton_Annotation {
}

因?yàn)锳pplicationComponent有依賴@scope也就是@Singleton,使用HttpCompotent 也需要依賴@scope啄骇,但又不能和ApplicationComponent一樣痴鳄,使用我們就參照@Singleton的格式復(fù)制了一份名叫@Applicaton_Annotation。
這樣Rebuild Project就不會(huì)報(bào)錯(cuò)了肠缔,說明Dagger注入成功夏跷。接下來我們來使用Dagger

public class MainActivity extends AppCompatActivity {
    String TAG = "MainActivity";
    TextView textView;
    @Inject
    HttpApi httpApi;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.tv);
        DaggerHttpCompotent.builder()
                .applicationComponent(((Application) getApplication()).getApplicationComponent()).build().getactivity(this);
//因?yàn)镠ttpCompotent依賴了ApplicationCompotent,所以需要傳入ApplicationCompotent對(duì)象明未,我們需要在Application里創(chuàng)建一個(gè)ApplicationCompotent對(duì)象
        httpApi.getweather().enqueue(new Callback<WeatherBean>() {
            @Override
            public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
                Log.i("http", response.isSuccessful() + "" + response.body().getWeatherinfo().getCity());
                textView.setText(response.body().getWeatherinfo().getCity());
            }

            @Override
            public void onFailure(Call<WeatherBean> call, Throwable t) {
            }
        });
    }
}

//Application .java
public class Application extends android.app.Application {
    ApplicationComponent applicationComponent;

    public ApplicationComponent getApplicationComponent() {
        return applicationComponent;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        applicationComponent=   DaggerApplicationComponent.create();
    }
}

這樣我們就完成了Dagger的更高級(jí)的用法槽华,就是對(duì)Retrofit的單例使用,可以避免重復(fù)的實(shí)例Retrofit趟妥。
最后我們來總結(jié)一下Dagger的使用注意事項(xiàng)

  1. componet 的 inject 方法接收父類型參數(shù)猫态,而調(diào)用時(shí)傳入的是子類型對(duì)象則無法注入
  2. component關(guān)聯(lián)的modules中不能有重復(fù)的provide
  3. module 的 provide 方法使用了 scope ,那么 component 就必須使用同一個(gè)注解
  4. module 的 provide 方法沒有使用 scope ,那么 component 和 module 是否加注解都無關(guān)緊要亲雪,可以通過編譯
  5. component的dependencies與component自身的scope不能相同勇凭,即組件之間的scope不同
  6. 沒有scope的component不能依賴有scope的component
  7. @Singleton 的生命周期依附于component,同一個(gè)module provide singleton ,不同component 也是不一樣
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末义辕,一起剝皮案震驚了整個(gè)濱河市虾标,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灌砖,老刑警劉巖璧函,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異基显,居然都是意外死亡蘸吓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門撩幽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來库继,“玉大人,你說我怎么就攤上這事窜醉∠芴眩” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵酱虎,是天一觀的道長雨膨。 經(jīng)常有香客問我,道長读串,這世上最難降的妖魔是什么聊记? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮恢暖,結(jié)果婚禮上排监,老公的妹妹穿的比我還像新娘。我一直安慰自己杰捂,他們只是感情好舆床,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嫁佳,像睡著了一般挨队。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蒿往,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天盛垦,我揣著相機(jī)與錄音,去河邊找鬼瓤漏。 笑死腾夯,一個(gè)胖子當(dāng)著我的面吹牛颊埃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蝶俱,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼班利,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了榨呆?” 一聲冷哼從身側(cè)響起罗标,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎积蜻,沒想到半個(gè)月后馒稍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浅侨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了证膨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片如输。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖央勒,靈堂內(nèi)的尸體忽然破棺而出不见,到底是詐尸還是另有隱情,我是刑警寧澤崔步,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布稳吮,位于F島的核電站,受9級(jí)特大地震影響井濒,放射性物質(zhì)發(fā)生泄漏灶似。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一瑞你、第九天 我趴在偏房一處隱蔽的房頂上張望酪惭。 院中可真熱鬧,春花似錦者甲、人聲如沸春感。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鲫懒。三九已至,卻和暖如春刽辙,著一層夾襖步出監(jiān)牢的瞬間窥岩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工扫倡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谦秧,地道東北人竟纳。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像疚鲤,于是被迫代替她去往敵國和親锥累。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容