在 Dagger2 知識梳理(1) - Dagger2 依賴注入的兩種方式 中,咱們介紹了兩種依賴注入的方式,其中第二種是經過給注入器Component
指定Module
,再由Module
提供建立實例的方法,來實現依賴注入,這是一種「自給自足」的方式,在這種狀況下,咱們的Component
是這麼聲明的: java
Component
能夠經過其餘的
Component
完成依賴注入,能夠劃分爲:
依賴方式 和
繼承方式。
Component
中指定它所依賴的Component
名字:
Component
須要聲明它能夠提供哪些類的實例化,所以它須要在Component
中聲明一些返回值爲這些類的方法:
Component
類須要用@SubComponent
聲明,這種狀況下,它通常相似於下面這樣:
Component
的實例來完成依賴注入,而是須要由父Component
實例提供一個getXXX
來將這個SubComponent
返回給使用者,SubComponent
自動擁有了父Component
注入對象的能力。
依賴方式和繼承方式的共同點就是,它們都是經過別的Component
來完成依賴注入的。下面,咱們先經過兩個簡單的例子,來演示如何使用這兩種方式完成注入,這篇文章的完整代碼能夠從 Dagger2Sample 的第三章獲取。git
當採用「依賴方式」來實現時,首先須要定義一個被依賴的Component
,咱們用DependencyComponent
來實現,它能夠提供一個數據源,即DependencySource
:github
public class DependencySource {
public String getData() {
return "獲取到來自依賴 Component 的數據";
}
}
複製代碼
和前面介紹的同樣,該數據源經過一個Component
和一個Module
來提供:小程序
@Component(modules = DependencyModule.class)
public interface DependencyComponent {
DependencySource getDependencySource();
}
複製代碼
@Module
public class DependencyModule {
@Provides
DependencySource provideDependencySource() {
return new DependencySource();
}
}
複製代碼
注意上面的DependencyComponent
,和前面不一樣,咱們不在它裏面聲明一個inject
接口,而是聲明瞭一個getDependencySource
接口,返回值爲DependencySource
,表示能夠給被它依賴的Component
提供DependencySource
這種類型的實例。ide
接下來,咱們建立一個SourceComponent
:ui
@Component(dependencies = DependencyComponent.class)
public interface SourceComponent {
public void inject(DataRepository dataRepository);
}
複製代碼
在Component
註解中,採用dependencies
來指明它所依賴的Component
,接下來,建立一個DataRepository
,經過依賴注入的方式來實例化它的DependencySource
成員變量,具體的操做步驟爲:this
@Inject
聲明須要注入的變量mDependencySource
make
編譯DaggerDependencyComponent
實例化依賴的DependencyComponent
DaggerSourceComponent
,在構造的過程當中,傳入第二步中的DependencyComponent
DaggerSourceComponent
的inject
方法完成注入public class DataRepository {
@Inject
DependencySource mDependencySource;
public DataRepository() {
//1.實例化所依賴的Component。
DependencyComponent dependencyComponent = DaggerDependencyComponent.create();
//2.在構建時傳入依賴的Component實例。
DaggerSourceComponent.builder().dependencyComponent(dependencyComponent).build().inject(this);
}
public String getDependencyData() {
return mDependencySource.getData();
}
}
複製代碼
當經過這種依賴於其它Component
方式完成注入時,Dagger2
會去依賴的Component
中查找它是否聲明瞭 返回值爲須要實例化的類的方法,若是有,那麼就經過該Component
來完成注入。spa
整個流程以下圖所示: 3d
對於被依賴的Component
,它聲明本身能夠提供哪些類的實例化,可是並不知道具體有哪些Component
須要依賴它。code
在第二節的例子中,咱們讓SourceComponent
依賴於DependencyComponent
,完成DependencySource
的依賴注入。
下面,咱們演示讓SourceComponent
被其餘的Component
繼承,使得其餘Component
能夠經過它來完成依賴注入,這裏惟一的不一樣,就是該Component
須要定義一個getSubSourceComponent()
來返回子Component
,關於SubSourceComponent
在3.2
中會進行介紹。
@Component(dependencies = DependencyComponent.class, modules = SourceModule.class)
public interface SourceComponent {
public void inject(DataRepository dataRepository);
//SubSourceComponent 爲子 Component。
SubSourceComponent getSubSourceComponent();
}
複製代碼
@Module
public class SourceModule {
@Provides
LocalSource provideLocalSource() {
return new LocalSource();
}
}
複製代碼
public class LocalSource {
public String getLocalData() {
return "獲取到本地數據";
}
}
複製代碼
下面,咱們來定義SubSourceComponent
,與以前的Component
不一樣,在接口上,加上的是@SubComponent
註解,而且不須要給它指定一個Module
,由於它是經過父Component
來實現實例化對象的。
@Subcomponent
public interface SubSourceComponent {
public void inject(SubRepository subRepository);
}
複製代碼
接下來,須要經過如下幾步來完成依賴注入:
@Inject
標籤make
,完成一次編譯SourceComponent
3.1
中SourceComponent
定義的getSubSourceComponent
獲取到SubSourceComponent
實例。SubSourceComponent
的inject
方法完成注入。public class SubRepository {
@Inject
LocalSource mLocalSource;
public SubRepository() {
//1.實例化所依賴的Component。
DependencyComponent dependencyComponent = DaggerDependencyComponent.create();
//2.在構建時傳入依賴的Component實例。
SourceComponent sourceComponent = DaggerSourceComponent.builder().dependencyComponent(dependencyComponent).build();
//3.獲取SubComponent。
SubSourceComponent subSourceComponent = sourceComponent.getSubSourceComponent();
//4.完成依賴注入。
subSourceComponent.inject(this);
}
public String getLocalData() {
return mLocalSource.getLocalData();
}
}
複製代碼
經過繼承方式來實現依賴注入時,父Component
也就是SourceComponent
須要聲明一個getXXX
方法,該方法返回子Component
,這個子Component
須要加上@SubComponent
註解,它不用本身聲明Module
,而是經過與父Component
關聯的Module
來完成依賴注入。
整個流程圖以下所示:
下面,咱們用一段小程序來演示上面的運行結果:
public class ComponentActivity extends AppCompatActivity {
private static final String TAG = ComponentActivity.class.getSimpleName();
private Button mBtnGetData;
private Button mBtnGetNetData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qualifier);
mBtnGetData = (Button) findViewById(R.id.bt_get_data);
mBtnGetData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DataRepository repository = new DataRepository();
String data = repository.getDependencyData();
Toast.makeText(ComponentActivity.this, data, Toast.LENGTH_SHORT).show();
}
});
mBtnGetNetData = (Button) findViewById(R.id.bt_get_net_data);
mBtnGetNetData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SubRepository repository = new SubRepository();
String data = repository.getLocalData();
Toast.makeText(ComponentActivity.this, data, Toast.LENGTH_SHORT).show();
}
});
}
}
複製代碼