依賴注入:
當一個類的實例需要另一個類的實例協(xié)助時寨躁,在傳統(tǒng)的程序設計過程中穆碎,通常有調用者來創(chuàng)建被調用者的實例。然而采用依賴注入的方式职恳,創(chuàng)建被調用者的工作不再由調用者來完成所禀,因此叫控制反轉,創(chuàng)建被調用者的實例的工作由IOC容器來完成放钦,然后注入調用者色徘,因此也稱為依賴注入。依賴注入是為了 降低耦合性操禀,即降低耦合就是降低類和類之間依賴關系褂策。
Dagger2用到的依賴注入的標識:
- @Inject: 在需要依賴的地方使用這個注解。這樣颓屑,Dagger2就會構造一個這個類的實例并滿足他們的依賴辙培。
- @Module: Modules類里面的方法專門提供依賴,因此當定義一個類邢锯,用@Module注解,這樣Dagger2在構造類的實例的時候搀别,就知道從哪里去找到需要的 依賴丹擎。
- @Component: 用來為“被注入方“提供其所需要的注入類。是@Inject和@Module的橋梁,它的主要作用就是連接這兩個部分蒂培。Components接口提供了所有定義的類型的實例再愈。
- @Provide: 在Modules類中,我們定義的方法是用這個注解护戳,以此來告訴Dagger2我們想要構造對象并提供這些依賴翎冲。
- @Scope: Dagger2可以通過自定義注解限定注解作用域。
- Qualifier: 當類的類型不足以鑒別一個依賴的時候媳荒,我們就可以使用這個注解標示抗悍。
- @Singleton: 當前提供的對象將是單例模式 ,一般配合@Provides
一起出現(xiàn)。
使用Dagger 2
- 由于 Dagger 使用 apt 生成代碼钳枕,因此添加apt插件
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
//添加apt插件
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
- 在build.gradle添加如下
//應用apt插件
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
...
provided 'org.glassfish:javax.annotation:10.0-b28'
compile 'com.google.dagger:dagger:2.5'
compile 'com.google.dagger:dagger-compiler:2.5'
}
- 創(chuàng)建登錄的LoginActivity
public class LoginActivity extends AppcompatActivity implemets ILoginView,View.OnClickListener{
private Button mLogin;
...
// 利用注解缴渊,Activity 持有了Presenter 的引用并且創(chuàng)建了該對象
@Inject
ILoginPresenterCompl loginPresenter;
@Override
protected void onCreate(Bundle saveInstanceState) {
...
DaggerMainComponent
.builder()
.mainModule(new MainModule(this))
.build()
.inject(this);
}
...
}
- 實現(xiàn)LoginPresenter接口的LoginPresenterCompl
public class LoginPresenterCompl implemets LoginPresenter{
private ILoginView mLoginView;
private User usr;
@Inject
public LoginPresenterCompl(ILoginView loginView){
this.mLoginView = loginView;
this.usr = new User("mm", "123");
}
...
}
- 創(chuàng)建MainModule,設置ILoginView的引用鱼炒,讓LoginActivity與 LoginPresenter解耦
@Module
public class MainModule {
private final ILoginView mLoginView;
public MainModule(ILoginView mLoginView){
this.mLoginView = mLoginView;
}
@Provides
ILoginView provideILoginView(){
return mLoginView;
}
}
- 創(chuàng)建MainComponent接口衔沼,連接MainModule與inject
@Component(modules = MainModule.class)
public interface MainCompenent{
public void inject(LoginActivity mLoginActivity );
}
分析:
LoginActivity 中需要 LoginPresenterCompl 的實例,所以在 LoginActivity 中定義了該對象并且通過 @Inject 將其注解昔瞧,同時到 LoginPresenterCompl 的構造方法中也通過 @Inject 將其注解指蚁, 表明這些是需要依賴注入的。
因為在 LoginPresenterCompl 的構造方法需要 ILoginView 類型的參數自晰,所以需要通過依賴將獲取這些參數凝化,所以就需要帶有 @Module 注解的 MainModule 類用于獲取需要的參數,在 @Module 注解的類中通過被 @Provides 注解的以 provide 開頭的 provideILoginView 方法對外提供需要的參數缀磕,一般而言有幾個參數就需要有幾個帶有 @Provides 的方法缘圈。
而帶有 @Component 的 MainComponent 接口或抽象類就起到連接@inject 和 @Module 的橋梁的作用。注解中有一個 module 的值袜蚕,這個值指向需要依賴的 Module 類糟把,同時其中有一個抽象方法 inject(),其中的參數就是我們需要在哪個類中實例化 LoginPreserentCompl牲剃,因為我們需要在 LoginActivity 中實例化遣疯,所以參數類型就是 LoginActivity 類型。
當我們 rebuild 的一下項目凿傅,在項目的 build/generated/source/apt/debug/項目包名/dragger 目錄下生成對應的包其中包含 DaggerMainComponent 類缠犀,這個類名其實不是固定的,是根據我們上面寫的 MainComponent聪舒,加了 Dagger 前綴生成的 DaggerMainComponent辨液。