国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

dagger2使用方法教程之簡明講解

2019-12-12 01:01:56
字體:
來源:轉載
供稿:網友

前言

Dagger 這個庫的取名不僅僅來自它的本意“匕首”,同時也暗示了它的原理。Jake Wharton 在對 Dagger 的介紹中指出,Dagger 即 DAG-er,這里的 DAG 即數據結構中的 DAG――有向無環圖(Directed Acyclic Graph)。也就是說,Dagger 是一個基于有向無環圖結構的依賴注入庫,因此Dagger的使用過程中不能出現循環依賴。

Android開發從一開始的MVC框架,到MVP,到MVVM,不斷變化?,F在MVVM的data-binding還在實驗階段,傳統的MVC框架Activity內部可能包含大量的代碼,難以維護,現在主流的架構還是使用MVP(Model + View + Presenter)的方式。但是 MVP 框架也有可能在Presenter中集中大量的代碼,引入DI框架Dagger2 可以實現 Presenter 與 Activity 之間的解耦,Presenter和其它業務邏輯之間的解耦,提高模塊化和可維護性。

現在的公司項目用到了Dagger2,之前只是稍微了解一些,沒有用過,然后查了查資料,整理如下,方便快速上手

四個基本注解

1、@Inject 主要有兩個作用,一個是使用在構造函數上,通過標記構造函數讓Dagger2來使用(Dagger2通過Inject標記可以在需要這個類實例的時候來找到這個構造函數并把相關實例new出來)從而提供依賴,另一個作用就是標記在需要依賴的變量讓Dagger2為其提供依賴。

@Inject注解的字段不能是private和protected的

2、@Module 用Module標注的類是專門用來提供依賴的。有的人可能有些疑惑,看了上面的@Inject,需要在構造函數上標記才能提供依賴,那么如果我們需要提供的類構造函數無法修改怎么辦,比如一些jar包里的類,我們無法修改源碼。這時候就需要使用Module了。Module可以給不能修改源碼的類提供依賴,當然,能用Inject標注的通過Module也可以提供依賴。

這里需要注意,Module和Inject這兩個注解還是有區別的,@Inject使用在構造函數上的時候,這個構造函數有沒有參數都可以,如果有參數的話這個Module也需要有其他Module或者@Inject構造函數提供實例,適合在提供該類自己的時候使用。但是如果用@Module的話,@Module注解的這個類需要有默認無參構造函數(顯示隱式都可以),否則會報“”xxx must be set”。如果沒有默認無參構造函數,就需要手動把這個Module的實例傳入Component,一般在MVP模式里使用該方式,用來提供Activity實例給Presenter實例。

所以,如果該類只需要提供自己,建議直接使用@Inject函數,如果是用來提供其他類的實例,建議使用@Module的方式。

3、@Provides 用Provides來標注一個方法,該方法可以在需要提供依賴時被調用,從而把預先提供好的對象當做依賴給標注了@Inject的變量賦值。provides主要用于標注Module里的方法。

4、@Component 一般用來標注接口,被標注了Component的接口在編譯時會產生相應的類的實例來作為提供依賴方和需要依賴方之間的橋梁,把相關依賴注入到其中。

四個擴展注解

1、@Qulifier 這里有個概念,叫依賴迷失,就是在Module注解的類里,有2個Provides都提供某個類的實例,這時候不用@Qulifier注解的話Component會不知道用哪個實例,這時候就要使用@Qulifier,下面直接提供代碼

@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface A {}
@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface B {}
@Modulepublic class SimpleModule { @Provides @A Cooker provideCookerA(){ return new Cooker("James","Espresso"); } @Provides @B Cooker provideCookerB(){ return new Cooker("Karry","Machiato"); }}
public class ComplexMaker implements CoffeeMaker { Cooker cookerA; Cooker cookerB; @Inject public ComplexMaker(@A Cooker cookerA,@B Cooker cookerB){ this.cookerA = cookerA; this.cookerB = cookerB; }}

2、@Named 和@Qulifier一樣,并且@Named就是繼承@Qulifier的,而且用起來比@Qulifier方便,示例代碼如下:

@Modulepublic class MainModule { @Provides @Named("red") public Cloth getRedCloth() { Cloth cloth = new Cloth(); cloth.setColor("紅色"); return cloth; } @Provides @Named("blue") public Cloth getBlueCloth() { Cloth cloth = new Cloth(); cloth.setColor("藍色"); return cloth; } @Provides public Clothes getClothes(@Named("blue") Cloth cloth){ return new Clothes(cloth); }}
public class MainActivity extends AppCompatActivity { ... @Inject @Named("red") Cloth redCloth; @Inject @Named("blue") Cloth blueCloth; @Override protected void onCreate(Bundle savedInstanceState) { ... tv.setText("我現在有" + redCloth + "和" + blueCloth ); }}

3、@Scope 局部單例,意思就是在被注入類里只有一個該類的實例,局部范圍是啥,那就是它生命周期范圍內。直接上代碼

//PerActivity.java@Scope@Retention(RetentionPolicy.RUNTIME)public @interface PerActivity {}
//ActivityModule.java@Modulepublic class ActivityModule { @Provides CoffeeShop provideCoffeeShop(){ return CoffeeShop.getInstance();//一個普通的單例 } /** * 直接在這里說結果,@PerActivity是用@Scope注解的,除了在這里注解還需要在用到該Module類的Component的類名上方也要注解,然后該實例在注入到某個類里的時候用同一個Component就會不管有幾個字段都會只有一個實例。注意:如果用不同的Component實例的話仍然會新的CookerFactory實例,單例CookerFactory只存在一個Component實例里。所以叫局部單例。 */ @Provides @PerActivity CookerFactory provideCookerFactory(){ return new CookerFactory(); } @Provides CookerFactoryMulty provideCookerFactoryMulty(){ return new CookerFactoryMulty();//非單例 }}
//CoffeeShop.javapublic class CoffeeShop { private static CoffeeShop INSTANCE; private CoffeeShop(){ Log.d("TAG","CoffeeShop New Instance"); } public static CoffeeShop getInstance(){ if(INSTANCE == null){ INSTANCE = new CoffeeShop(); } return INSTANCE; }}//CookerFactory.javapublic class CookerFactory { public CookerFactory(){ Log.d("TAG","CookerFactory New Instance"); }}//CookerFactoryMulty.javapublic class CookerFactoryMulty { public CookerFactoryMulty(){ Log.d("TAG","CookerFactoryMulty New Instance"); }}
//除了在Module的Provides方法里寫上@Scope還需要在Component類名上方寫上,這里自定義的@Scope名字叫PerActivity@PerActivity@Component(modules = {ActivityModule.class})public interface ActivityComponent { void inject(MainActivity simpleActivity);}
public class MainActivity extends Activity { ActivityComponent activityComponent; @Inject CoffeeShop coffeeShop1; @Inject CoffeeShop coffeeShop2; @Inject CookerFactory cookerFactory1; @Inject CookerFactory cookerFactory2; @Inject CookerFactoryMulty cookerFactoryMulty1; @Inject CookerFactoryMulty cookerFactoryMulty2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activityComponent = DaggerActivityComponent.builder() //下面這句話可以不寫,因為Module有默認構造函數。如果Module的構造器里有參數,并且該參數不是注入進去的,就需要用類似下面的方法手動設置實例到Component中 .activityModule(provideModule()) .applicationComponent(MyApplication.getComponent()).build(); activityComponent.inject(this); coffeeFactory.run(); }  private ActivityModule provideModule(){ return new ActivityModule(); }}

運行結果

07-11 16:53:27.978 1927-1927/? D/TAG

主站蜘蛛池模板:
邵东县|
广西|
保山市|
天台县|
辰溪县|
仁怀市|
西华县|
安塞县|
蒙阴县|
巴青县|
张家界市|
渭源县|
军事|
江达县|
色达县|
蒙山县|
泰兴市|
疏附县|
祁东县|
淮滨县|
沛县|
永登县|
河池市|
曲麻莱县|
沙湾县|
潼关县|
新营市|
出国|
靖江市|
德兴市|
凯里市|
北票市|
甘谷县|
府谷县|
普兰店市|
宜丰县|
宁陕县|
龙胜|
察雅县|
柞水县|
桃江县|