Dagger2 知識梳理(3) 使用 dependencies 和 @SubComponent 完成依賴注入

1、前言

Dagger2 知識梳理(1) - Dagger2 依賴注入的兩種方式 中,咱們介紹了兩種依賴注入的方式,其中第二種是經過給注入器Component指定Module,再由Module提供建立實例的方法,來實現依賴注入,這是一種「自給自足」的方式,在這種狀況下,咱們的Component是這麼聲明的: java

指定 Module
除此以外,還有另外兩種方式,讓 Component能夠經過其餘的 Component完成依賴注入,能夠劃分爲: 依賴方式繼承方式

  • 經過依賴方式實現時,須要在Component中指定它所依賴的Component名字:
    依賴方式下的 Component
    而被依賴的Component須要聲明它能夠提供哪些類的實例化,所以它須要在Component中聲明一些返回值爲這些類的方法:
    依賴方式下的被依賴 Component
  • 經過繼承方式時實現時,子Component類須要用@SubComponent聲明,這種狀況下,它通常相似於下面這樣:
    繼承方式下的子 SubComponent
    而且咱們不能直接建立該Component的實例來完成依賴注入,而是須要由父Component實例提供一個getXXX來將這個SubComponent返回給使用者,SubComponent自動擁有了父Component注入對象的能力。
    繼承方式下的父 Component

依賴方式和繼承方式的共同點就是,它們都是經過別的Component來完成依賴注入的。下面,咱們先經過兩個簡單的例子,來演示如何使用這兩種方式完成注入,這篇文章的完整代碼能夠從 Dagger2Sample 的第三章獲取。git

2、使用依賴方式完成注入

2.1 定義被依賴的 DependencyComponent

當採用「依賴方式」來實現時,首先須要定義一個被依賴的Component,咱們用DependencyComponent來實現,它能夠提供一個數據源,即DependencySourcegithub

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

2.2 定義依賴 DependencyComponent 的 SourceComponent

接下來,咱們建立一個SourceComponentui

@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
  • 調用DaggerSourceComponentinject方法完成注入
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();
    }
}
複製代碼

2.3 小結

當經過這種依賴於其它Component方式完成注入時,Dagger2會去依賴的Component中查找它是否聲明瞭 返回值爲須要實例化的類的方法,若是有,那麼就經過該Component來完成注入。spa

整個流程以下圖所示: 3d

依賴方式

對於被依賴的Component,它聲明本身能夠提供哪些類的實例化,可是並不知道具體有哪些Component須要依賴它。code

3、使用繼承方式完成注入

3.1 定義父 Component - SourceComponent

在第二節的例子中,咱們讓SourceComponent依賴於DependencyComponent,完成DependencySource的依賴注入。

下面,咱們演示讓SourceComponent被其餘的Component繼承,使得其餘Component能夠經過它來完成依賴注入,這裏惟一的不一樣,就是該Component須要定義一個getSubSourceComponent()來返回子Component,關於SubSourceComponent3.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 "獲取到本地數據";
    }
}
複製代碼

3.2 定義子 Component - SubSourceComponent

下面,咱們來定義SubSourceComponent,與以前的Component不一樣,在接口上,加上的是@SubComponent註解,而且不須要給它指定一個Module,由於它是經過父Component來實現實例化對象的。

@Subcomponent
public interface SubSourceComponent {
    public void inject(SubRepository subRepository);
}
複製代碼

接下來,須要經過如下幾步來完成依賴注入:

  • 在須要注入的變量上加上@Inject標籤
  • 點擊make,完成一次編譯
  • 首先實例化父SourceComponent
  • 經過在3.1SourceComponent定義的getSubSourceComponent獲取到SubSourceComponent實例。
  • 調用SubSourceComponentinject方法完成注入。
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();
    }

}
複製代碼

3.3 小結

經過繼承方式來實現依賴注入時,父Component也就是SourceComponent須要聲明一個getXXX方法,該方法返回子Component,這個子Component須要加上@SubComponent註解,它不用本身聲明Module,而是經過與父Component關聯的Module來完成依賴注入。

整個流程圖以下所示:

繼承方式

4、實例演示

下面,咱們用一段小程序來演示上面的運行結果:

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();
            }
        });
    }
}
複製代碼


更多文章,歡迎訪問個人 Android 知識梳理系列:

相關文章
相關標籤/搜索