安卓基礎(chǔ)開發(fā)庫,讓開發(fā)簡單點(diǎn)。
Demo地址:https://github.com/LJYcoder/MvpDagger
學(xué)習(xí)/參考地址:
http://www.itdecent.cn/p/cd2c1c9f68d4
https://blog.csdn.net/lisdye2/article/details/51942511
http://www.itdecent.cn/p/24af4c102f62
前言
Dagger2已經(jīng)出來挺久了,網(wǎng)上相關(guān)的教程也很多,普遍都說它比較難上手。
相比起其他框架確實(shí)如此,但只要學(xué)習(xí)后加以實(shí)踐,還是比較好明白的,說不定你還會從此對它愛不釋手。
我會盡量把它講得容易理解些,如有不當(dāng)之處,還請大家指出糾正。
什么是Dagger2
Dagger2是一個依賴注入(Dependency Injection)框架。
什么又是依賴注入呢?
借別人的話來說,就是“目標(biāo)類中所依賴的其他類的初始化過程,不是通過在目標(biāo)類中編碼的方式完成,而是通過其他手段把已經(jīng)初始化好的實(shí)例自動注入到目標(biāo)類中”。
再換種方式來說,就是把類實(shí)例的初始化過程都挪至一個地方統(tǒng)一管理,具體需要哪個實(shí)例時,就從這個地方取出(注入到目標(biāo)類中)。
使用Dagger2有什么好處
知其然,然后要知其所以然。
1. 解耦
假設(shè)有一個A類,項目中很多地方都使用到它(在很多地方通過new A()對A實(shí)例進(jìn)行了初始化)。然后由于需求變動,A的構(gòu)造函數(shù)增加了一個參數(shù)。
好了,牽一發(fā)而動全身,你需要把各個new A()的地方都進(jìn)行修改。
但如果是使用Dagger2進(jìn)行管理,你只需在類實(shí)例的供應(yīng)端進(jìn)行修改即可。
2. 讓功能實(shí)現(xiàn)更專注于功能實(shí)現(xiàn)
假設(shè)現(xiàn)在你需要調(diào)用A類的x()方法來實(shí)現(xiàn)某功能,但是A類的構(gòu)造過程相當(dāng)?shù)膹?fù)雜(這樣的例子可以參考GreenDao中獲取XXXDao、Retrofit中獲取Observable請求)
public void xxx(){
E e = new E();
D d = new D(e);
C c = new C();
B b = new B(c,d);
A a = new A(b);
a.x();
}
結(jié)果6行代碼中,構(gòu)造實(shí)例a占了5行,調(diào)用x()方法實(shí)現(xiàn)功能卻只占了1行。
但如果使用Dagger2進(jìn)行管理,將a實(shí)例的構(gòu)造過程移至實(shí)例供應(yīng)端,則功能實(shí)現(xiàn)模塊的代碼會變成這樣
@Injcet
A a;
public void xxx(){
a.x();
}
這就是所說的讓功能實(shí)現(xiàn)更專注于功能實(shí)現(xiàn),而不必去管a實(shí)例的構(gòu)造過程。
3. 更好地管理類實(shí)例
通常我們開發(fā)中會有兩種類實(shí)例:
一種是全局實(shí)例(單例),它們的生命周期與app保持一致。
一種是頁面實(shí)例,它們的生命周期與頁面保持一致。
通過Dagger2,我們可以使用一個組件專門管理全局類實(shí)例(也免去了單例的寫法,不用考慮餓漢懶漢什么的);然后各個頁面也有各自組件去管理它們的頁面實(shí)例。
這樣不管是對于實(shí)例的管理,還是項目的結(jié)構(gòu),都會變得更加的清晰明了。
4. 逼格高
(這點(diǎn)可以略過...)
當(dāng)你不認(rèn)識Dagger2卻看著使用Dagger2的項目代碼,很可能會感覺到一種茫然與高大上:
各種@Inject,@Provides,@Singleton,Lazy<>,Provider<>等是什么鬼?
為什么沒有實(shí)例化的代碼?
為什么明明是null卻不會報空指針?
等你學(xué)會使用Dagger2之后,你也可以來一波"高逼格"的代碼。
當(dāng)然,這里也不得不提一下,使用Dagger2會增加代碼量。所以如果是小項目/獨(dú)立開發(fā),你也可以考慮不用,因?yàn)槟憧赡苡蟹N失大于得的感覺。如果是大項目/團(tuán)隊開發(fā),使用后就得大于失了。
角色介紹
在講用法前,先對幾個重要角色進(jìn)行了解。
實(shí)例需求端
一個類中,它包含了實(shí)例成員,在使用這些實(shí)例前,需要對它們進(jìn)行初始化,但前面已經(jīng)說了初始化的過程挪至其他地方。所以這個類的需求是,已經(jīng)完成初始化的實(shí)例對象。
暫且把這樣的類稱為“實(shí)例需求端”。
實(shí)例供應(yīng)端
進(jìn)行實(shí)例初始化的地方,并對外供應(yīng)所需的實(shí)例。
Dagger2中,供應(yīng)端有兩種方式可以供應(yīng)實(shí)例:(后面會介紹)
第一種:使用Module
第二種:使用@Inject標(biāo)注構(gòu)造函數(shù)
橋梁
實(shí)例供應(yīng)端并不知道它要供應(yīng)的實(shí)例交給誰。
這個時候就需要通過橋梁,將實(shí)例需求端與實(shí)例供應(yīng)端聯(lián)系在一起。
Dagger2中,Component就負(fù)責(zé)扮演橋梁的角色。
使用介紹
1. 初步使用
1.1 添加依賴
compile 'com.google.dagger:dagger:2.14.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
1.2 處理實(shí)例需求端
在實(shí)例需求端中,使用@Inject標(biāo)注需要注入的實(shí)例變量。
public class UploadActivity extends AppCompatActivity{
@Inject
UploadPresenter mPresenter;
}
1.3 處理實(shí)例供應(yīng)端
前面說了,供應(yīng)端有兩種方式可以供應(yīng)實(shí)例。
方式一 使用Module
- 使用@Module標(biāo)注類,表示它為供應(yīng)端
- 在類中使用@Provides標(biāo)注方法,表示它為提供實(shí)例的方法。
在該方法中對實(shí)例進(jìn)行初始化并返回該實(shí)例。
@Module
public class UploadActivityModule {
@Provides
UploadPresenter uploadPresenter() {
return new UploadPresenter();
}
}
方式二 使用@Inject標(biāo)注構(gòu)造函數(shù)
public class UploadPresenter{
@Inject
public UploadPresenter() {
}
}
注意
方式一的優(yōu)先級高于方式二,意思就是:
- 在供應(yīng)某實(shí)例時,會先通過方式一查找是否存在返回該實(shí)例的的方法
- 如果存在,則獲取實(shí)例并對外供應(yīng)
- 如果不存在,再通過方式二查找是否存在@Inject標(biāo)注的構(gòu)造函數(shù)
- 如果存在,則將通過該構(gòu)造函數(shù)構(gòu)造實(shí)例并對外供應(yīng)
- 如果不存在,那將報錯,因?yàn)闊o法供應(yīng)所需的實(shí)例
1.4 搭建橋梁
- 使用@Component標(biāo)注接口,表示它為橋梁。
(如果使用1.3.1的方式供應(yīng)實(shí)例,則需在@Component(modules=xxx.class)中指明module。)
一個Component可以沒有module,也可以同時有多個module。 - 添加 void inject(實(shí)例需求端) 方法,表明實(shí)例供應(yīng)端中的實(shí)例將交給該實(shí)例需求端。
通過這個方法,查找實(shí)例需求端中需要注入的實(shí)例有哪些(使用@Inject標(biāo)注的那些實(shí)例),然后在實(shí)例供應(yīng)端中獲取所需的實(shí)例,最后注入到實(shí)例需求端中 - 用來注入的方法,它的方法名不一定要是inject,可以隨便取,一般都取inject。但該方法的返回類型必須為void
@Component(modules = UploadActivityModule.class)
public interface UploadActivityComponent {
void inject(UploadActivity uploadActivity);
}
1.5 編譯,注入
- 完成以上幾步后,ReBuild一下項目以生成DaggerUploadActivityComponent類。
- 在實(shí)例需求端中調(diào)用inject完成實(shí)例的注入
public class UploadActivity extends AppCompatActivity{
@Inject
UploadPresenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入實(shí)例
DaggerUploadActivityComponent.builder()
.build()
.inject(this);
//注入后即可調(diào)用mPresenter中的方法了
mPresenter.xxx();
}
}
到此,Dagger2的初步使用就結(jié)束了,下面開始講解些進(jìn)階用法。
2. 接收外部參數(shù)
有些時候,實(shí)例的初始化需要接收外部參數(shù)才能完成,比如MVP中的Presenter往往需要傳入IView接口以便完成數(shù)據(jù)回調(diào)。
現(xiàn)在UploadPresenter的構(gòu)造函數(shù)發(fā)生了變動,需傳入IUploadView。
public class UploadPresenter{
IUploadView mIView;
public UploadPresenter(IUploadView iview) {
mIView = iview;
}
}
那在供應(yīng)端中,如何接收外部參數(shù)IUploadView呢?
下面介紹兩種方式:
2.1 方式一 通過Module的構(gòu)造函數(shù)傳入
對實(shí)例供應(yīng)端的module進(jìn)行改造
@Module
public class UploadActivityModule {
IUploadView mIView;
public UploadActivityModule(IUploadView iview) {
mIView = iview;
}
@Provides
IUploadView iUploadView(){
return mIView;
}
@Provides
UploadPresenter uploadPresenter(IUploadView iview) {
return new UploadPresenter(iview);
}
}
- 添加了構(gòu)造函數(shù)以便獲取外部參數(shù)IUploadView
- uploadPresenter()方法添加了IUploadView參數(shù)
- 到時構(gòu)建UploadPresenter實(shí)例時,會在這個Module或者同個Component下的其他Module中查找是否存在返回IUploadView的的方法
- 如果存在,則通過該方法獲取IUploadView以構(gòu)造UploadPresenter
- 如果不存在,則通過1.3.2方式查找是否存在@Inject標(biāo)注的構(gòu)造函數(shù)(這個例子中當(dāng)然不會存在,因?yàn)镮UploadView是接口)
- 不直接使用mIView來構(gòu)造UploadPresenter是為了降低耦合度。uploadPresenter()方法只管獲取構(gòu)造Presenter所需的參數(shù),而該參數(shù)從哪來、以后會有哪些變動,交給該參數(shù)的供應(yīng)方法(iUploadView())處理即可。
利用Module構(gòu)造函數(shù)傳入外部參數(shù)
public class UploadActivity implements IUploadView{
@Inject
UploadPresenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入實(shí)例
DaggerUploadActivityComponent.builder()
.uploadActivityModule(new UploadActivityModule(this))//通過構(gòu)造函數(shù)傳入外部參數(shù)IUploadView
.build()
.inject(this);
//注入后即可調(diào)用mPresenter中的方法了
mPresenter.xxx();
}
//實(shí)現(xiàn)IUploadView接口的方法
@Override
public void onUploadSuccess() {
//上傳成功
}
@Override
public void onUploadFail() {
//上傳失敗
}
}
2.2 方式二 通過Component傳入
對橋梁Component進(jìn)行改造
@Component(modules = UploadActivityModule.class)
public interface UploadActivityComponent {
void inject(UploadActivity uploadActivity);
IUploadView iUploadView();
@Component.Builder
interface Builder {
@BindsInstance
Builder iUploadView(IUploadView iUploadView);
UploadActivityComponent build();
}
}
- 加入iUploadView()方法返回IUploadView
- 加入了Builder來接收IUploadView
構(gòu)建Component時傳入外部參數(shù)
public class UploadActivity extends AppCompatActivity implements IUploadView{
@Inject
UploadPresenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入實(shí)例
DaggerUploadActivityComponent.builder()
.iUploadView(this)
.build()
.inject(this);
//注入后即可調(diào)用mPresenter中的方法了
mPresenter.xxx();
}
//實(shí)現(xiàn)IUploadView接口的方法
@Override
public void onUploadSuccess() {
//上傳成功
}
@Override
public void onUploadFail() {
//上傳失敗
}
}
3. 限定符注解 @Qualifier
@Qualifier主要是用于解決,因?qū)嵗?yīng)端存在多個返回類型相同的供應(yīng)方法而引起歧義的問題。
下面舉個例子,現(xiàn)在頁面需有兩個Dialog,一個用于登錄,一個用于注冊。
3.1 使用@Named注解區(qū)分
Dagger2默認(rèn)提供了一個@Named注解,從代碼可以看出屬于@Qualifier的一種實(shí)現(xiàn)。
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {
String value() default "";
}
在供應(yīng)端對兩個Dialog進(jìn)行構(gòu)造。
@Module
public class TestActivityModule {
private Context mContext;
public TestActivityModule(Context context){
mContext = context;
}
@Provides
Context context(){
return mContext;
}
@Named("login")
@Provides
Dialog loginDialog(Context context){
Dialog dialog = new Dialog(context);
dialog.setTitle("登錄提示");
....
return dialog;
}
@Named("register")
@Provides
Dialog registerDialog(Context context){
Dialog dialog = new Dialog(context);
dialog.setTitle("注冊提示");
....
return dialog;
}
}
- 可以看到,在實(shí)例供應(yīng)端中,需在提供Dialog實(shí)例的方法上面加@Named注解以區(qū)分。如果不加則會報錯,因?yàn)镈agger2不知道要使用哪個方法來獲取Dialog實(shí)例。
@Component(modules = TestActivityModule.class)
public interface TestActivityComponent {
void inject(TestActivity testActivity);
}
public class TestActivity extends AppCompatActivity{
@Named("login")
@Inject
Dialog mDialogLogin;
@Named("register")
@Inject
Dialog mDialogRegister;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入實(shí)例
DaggerTestActivityComponent.builder()
.testActivityModule(new TestActivityModule(this))
.build()
.inject(this);
}
}
- 在實(shí)例需求端中,同樣要使用@Named注解標(biāo)注要注入的實(shí)例。讓Dagger2知道,
@Named("login")標(biāo)注的mDialogLogin,需要通過@Named("login")標(biāo)注的供應(yīng)方法來獲取。
@Named("register")標(biāo)注的mDialogRegister,需要通過@Named("register")標(biāo)注的供應(yīng)方法來獲取。
3.2 使用自定義@Qualifier區(qū)分
使用@Named注解的話,需要加入字符串來區(qū)分,這樣比較麻煩也容易出錯。所以我們可以使用自定義的限定符注解。
@Qualifier
public @interface DialogLogin {
}
@Qualifier
public @interface DialogRegister {
}
然后把前面涉及的@Named("login")換成@DialogLogin,@Named("register")換成@DialogRegister即可~
4. 作用域注解 @Scope
@Scope的作用是使同一個Component中供應(yīng)的實(shí)例保持唯一。
4.1 使用作用域注解實(shí)現(xiàn)局部單例
舉例說明:
public class UploadActivity extends AppCompatActivity{
@Inject
UploadPresenter mPresenter1;
@Inject
UploadPresenter mPresenter2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入實(shí)例
DaggerUploadActivityComponent.builder()
.build()
.inject(this);
}
}
- 如果不使用作用域注解,則代碼中的mPresenter1,mPresenter2將會是兩個不一樣的實(shí)例,可通過打印內(nèi)存地址查看。
- 而如下使用作用域注解后,則兩者將會是同一個實(shí)例,可通過打印內(nèi)存地址查看。
步驟1 自定義@Scope注解
@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScope {}
步驟2 橋梁Component添加作用域注解
@ActivityScope
@Component(modules = UploadActivityModule.class)
public interface UploadActivityComponent {
void inject(UploadActivity uploadActivity);
}
步驟3 供應(yīng)端中提供實(shí)例的方法添加作用域注解
@Module
public class UploadActivityModule {
@ActivityScope
@Provides
UploadPresenter uploadPresenter() {
return new UploadPresenter();
}
}
如果是使用1.3.2方式提供實(shí)例,則在類上方添加作用域注解
@ActivityScope
public class UploadPresenter{
@Inject
public UploadPresenter() {
}
}
經(jīng)過@Scope處理后,UploadActivity中的UploadPresenter實(shí)例將保持唯一。
4.2 使用作用域注解實(shí)現(xiàn)全局單例
全局單例,相信大家就很熟悉了,就是平時用餓漢懶漢等等寫的那種單例模式。
前面已經(jīng)說過@Scope作用是使同一個Component中供應(yīng)的實(shí)例保持唯一。
也就是說,如果我在另一個Activity中再創(chuàng)建了一個新的Component,那么它所提供的UploadPresenter實(shí)例也將是新的。這和我們理解的全局單例并不一樣。
所以,要想實(shí)現(xiàn)全局單例,那就要確保獲取實(shí)例的Component一直都是同一個。
如何實(shí)現(xiàn)呢?
答案是創(chuàng)建一個Component用于提供全局單例的實(shí)例(創(chuàng)建過程和4.1基本一樣),然后在Application中對該Component進(jìn)行初始化,以后要獲取單例時,都統(tǒng)一通過它來獲取。
全局性的實(shí)例供應(yīng)端
@Module
public class AppModule {
private Application mApplication;
public AppModule (Application application){
mApplication = application;
}
@Singleton
@Provides
Application application(){
return mApplication;
}
@Singleton
@Provides
ActivityStackManager activityStackManager() {
return new ActivityStackManager();
}
}
全局性的橋梁
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
ActivityStackManager activityStackManager();
Application application();
}
Application中初始化
public class MyApplication extends Application {
public static AppComponent mAppComponent;
@Override
public void onCreate() {
super.onCreate();
mAppComponent= DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
}
}
每次都通過Application中的AppComponent獲取某實(shí)例,即可保證全局單例
public class UploadActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication.mAppComponent.activityStackManager().pushOneActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
MyApplication.mAppComponent.activityStackManager().popOneActivity(this);
}
}
- 使用了Dagger2默認(rèn)提供的作用域注解@Singleton,通過源碼可以發(fā)現(xiàn)它的實(shí)現(xiàn)其實(shí)和前面的@ActivityScope是一樣的。
- 所以真正實(shí)現(xiàn)全局單例的不是并@Singleton,而是使用每次獲取實(shí)例都通過同一個Component。
- 但由于它的字面意思為單例,所以我們通常把它應(yīng)用在全局性的橋梁和實(shí)例供應(yīng)端中。
- 全局性的Component中沒有加入inject方法來自動注入(當(dāng)然你也可以這么做,但全局性的比較少這么做),而是加入了activityStackManager()方法,供外部調(diào)用來獲取實(shí)例。
5. Lazy<T> 和 Provider<T>
假如你并不希望在調(diào)用inject()方法后,就對@Inject標(biāo)注的實(shí)例進(jìn)行初始化注入,而是希望在用到該實(shí)例的時候再進(jìn)行初始化,那么我們就可以使用Lazy<T>和Provider<T>來實(shí)現(xiàn)。
舉例說明(省略實(shí)例供應(yīng)端和橋梁的代碼)
public class UploadActivity extends AppCompatActivity{
@Inject
Lazy<UploadPresenter> mPresenter1;
@Inject
Provider<UploadPresenter> mPresenter2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入實(shí)例
DaggerUploadActivityComponent.builder()
.build()
.inject(this);
}
public void xxx(){
//調(diào)用Lazy的get()方法后才開始初始化Presenter并得到該實(shí)例
//并且后面每次調(diào)用get()方法得到的實(shí)例都將是同一個。
mPresenter1.get().xxx();
//調(diào)用Provider的get()方法后才開始初始化Presenter并得到該實(shí)例
//并且后面每次調(diào)用get()方法,都會重新調(diào)用供應(yīng)端的供應(yīng)方法來獲取新實(shí)例。
mPresenter2.get().xxx();
}
}
注意: 如果使用了前面介紹的作用域注解@Scope控制了實(shí)例的唯一性,那么即使多次調(diào)用Provider的get()方法,得到的依然是同一個實(shí)例。
6. 依賴 和 包含
假設(shè)A供應(yīng)端某個實(shí)例的初始化過程需要用到X實(shí)例,而X實(shí)例在其他橋梁連接的B供應(yīng)端中有提供,那么我們可以我們可以通過橋梁間的依賴或包含,從B供應(yīng)端獲取需要的實(shí)例,這樣就不用再在A供應(yīng)端中寫X實(shí)例的提供方法了。
比如下面代碼中,DbHelper的初始化需要用到全局的Context(即Application),那么我們可以通過橋梁間的依賴或包含,從前面提及的全局AppComponent中獲取。
@Module
public class TestActivityModule {
//需要使用到Application參數(shù)
@Provides
DbHelper dbHelper(Application application){
return new DbHelper(application);
}
}
6.1 通過依賴實(shí)現(xiàn)(TestActivityComponent依賴AppComponent)
通過dependencies = xxx.classs指定要依賴的Component :
@Component(modules = TestActivityModule.class, dependencies = AppComponent.class)
public interface TestActivityComponent {
void inject(TestActivity testActivity);
}
被依賴的Component中需定義相關(guān)實(shí)例的獲取方法 :
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
Application application();
...
}
初始化TestActivityComponent時需傳入依賴的Component
public class TestActivity extends AppCompatActivity{
@Inject
DbHelper mDbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DaggerTestActivityComponent.builder()
.appComponent(MyApplication.mAppComponent) //傳入依賴的Component
.build()
.inject(this);
}
}
6.2 通過包含實(shí)現(xiàn)(AppComponent包含TestActivityComponent)
TestActivityComponent使用@Subcomponent注解而不是@Component
@Subcomponent(modules = TestActivityModule.class)
public interface TestActivityComponent {
void inject(TestActivity testActivity);
}
AppComponent中定義相關(guān)方法,用來包含和獲取SubComponent
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
TestActivityComponent addSub(TestActivityModule testActivityModule);
...
}
通過AppComponent來獲取SubComponent,然后注入
public class TestActivity extends AppCompatActivity{
@Inject
DbHelper mDbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TestActivityComponent testActivityComponent = MyApplication.mAppComponent.addSub(new TestActivityModule());
testActivityComponent .inject(this);
}
}
6.3 依賴和包含使用小結(jié)
- 通過橋梁Component之間的依賴或包含,可以獲取到其他橋梁所連接的供應(yīng)端提供的實(shí)例。
- 使用依賴實(shí)現(xiàn)的話(假設(shè)A依賴B),A需通過dependencies指定依賴B,B中需定義A所需的相關(guān)實(shí)例的獲取方法,A構(gòu)造時需傳入B。
- 使用包含實(shí)現(xiàn)的話(假設(shè)B包含A),A需使用@Subcomponent標(biāo)注,B中需定義方法來包含/獲取A,A是通過調(diào)用B的方法來獲取的。
- 具有依賴關(guān)系的兩個Component,它們的作用域注解@Scope必須不同,否則會引起歧義。
7. 一些Tips
Tips1:
在1.3.1和1.3.2介紹了兩種實(shí)例供應(yīng)方式:
方式一:使用Module。
方式二:使用@Inject標(biāo)注構(gòu)造函數(shù)。
那什么時候應(yīng)該使用哪種方式呢?
假設(shè)現(xiàn)在供應(yīng)端需要提供A類的實(shí)例
- 當(dāng)無法在A類的構(gòu)造函數(shù)上加入@Inject時(比如一些第三方庫里的類),則使用方式一提供A實(shí)例。
- 當(dāng)你希望在A類實(shí)例初始化時,A類中被@Inject標(biāo)注的變量也被自動注入,則使用方式二提供A實(shí)例。
Tips2:
Module類可以聲明為abstract抽象,但相關(guān)的供應(yīng)方法需聲明為static靜態(tài)方法。
Tips3:
@inject標(biāo)注的實(shí)例變量不能聲明為private,也不能為static,否則會編譯報錯。
Tips4:
如果module中的供應(yīng)方法聲明了@Scope,那么它所屬的component必須也聲明相同的@Scope。
但如果component聲明了@Scope,它的module的供應(yīng)方法并不一定全都要聲明@Scope。