(1)依賴注入概念
依賴注入未來單說就是非本身主動初始化依賴,而經過外部來傳入依賴的方式,咱們就稱爲依賴注。舉例來講:以下面的代碼所示,A是依賴注入的例子,B是非依賴注入的例子。汽車(Car)依賴輪胎(Tyre)的資源。android
【A:依賴注入的例子】git
public class Car { ... // 輪胎 Tyre tyre; ... public Car(Tyre tyre) { this.tyre = tyre; } }
【B:非依賴注入的例子】github
public class Car{ ... // 輪胎 Tyre tyre; ... public Car(Tyre tyre) { this.tyre = new Tyre(); } }
(2)Ioc容器:負責依賴注入控制器
如A所示,上文已經說了Car的實現依賴於外界傳入的Tyre。那麼負責傳入這個資源的角色就是Ioc容器。Ioc容器自己也不實際產生資源,它會請求其餘的對象來生成資源。由此來看,Car解除了和Tyre的依賴,而和Ioc產生了依賴:Car->Ioc容器。這樣的好處是,若是Car依賴於多個對象(方向盤,輪胎,地盤等等),那麼Car沒必要要和那麼多對象產生直接的依賴,而只須要依賴Ico容器便可。無論Car須要什麼資源,它只須要找Ico容器要便可。由此能夠看出,依賴注入就是要解決對象之間的依賴關係,即由對象->對象的直接依賴,轉化到對象->Ico的依賴。app
<img src="https://img-blog.csdn.net/201...; width="60%">框架
(3)依賴注入的好處ide
在Java裏面,存在大量的依賴注入的框架,如Spring等等。在Dagger2出來以前,Android也存在一些依賴注入框架如Dagger1。其均是依靠反射來實現依賴注入,所以會帶來必定的性能問題,所以這些框架並無在Android中流行起來。函數
Dagger2經過APT技術,經過在編譯的時候生成注入的工廠類代碼,解決了性能問題,所以Dagger2開始在Android上發揚光大。源碼分析
Dagger2實現原理如C圖所示,其主要由三部分組成性能
【C:dagger2實現原理】
<img src="https://img-blog.csdn.net/201...; width="60%">單元測試
總結起來就是,當被注入的對象須要Component去給他設置屬性的時候,Component就會去找它的Module去生成該對象。若是Module完成不了這件事情,Component就會去找它依賴的Component(Dependency Component)去給他生成該對象。Dependency Component自己也沒有生成對象能力,其就依賴它的Module去生成該對象
在瞭解Dagger2註解以前咱們首先記住2個東西:
- Dagger2全部對象匹配都是按照返回類型來匹配,與函數命名無關
- Dagger2的Scope的大小都是咱們人爲賦予的,Scope的大小不是名字決定的,而是Component之間的依賴關係決定的。
在2.1中所提的三種角色都是經過註解來完成的,dagger2經常使用註解以下:
(1)Component使用的註解
@Component
- 做用對象:Class - 代表該class是個Component
@Scope
- 做用對象:Class - 指明Component 範圍,其依賴的Model若是用@Scope修飾,必須與Component 的Scope相同
Component示例以下所示:
@BigScoped @Component(modules = {ActivityModule.class},dependencies = {AppComponent.class}) public interface ActivityComponent { void inject(Dagger2Activity dagger2Activity); ActivityScopeObj activityScopeObj(); ActivityObj activityObj(); }
(2)Module使用的註解
@Module
- 做用對象:Class - 代表該Class是個對象的生成器
@Provider
- 做用對象:Method - 代表該方法能對外提供對象:**按照返回的類型匹配**
@Scope
- 做用對象:Method - 代表該方法在Scope範圍內是個單例
Module示例:
@Module public class ActivityModule { @Provides public ActivityObj provideActivityObj() { return new ActivityObj(); } @Provides public FragmentNotVisibleObj provideActivityNotVisibleObj() { return new FragmentNotVisibleObj(); } @BigScoped @Provides public ActivityScopeObj provideActivityScopeObj() { return new ActivityScopeObj(); } }
(3)被注入對象使用的註解
@Inject
- 做用對象:Field - 代表該屬性依賴Component進行注入
代碼示例:
public class Dagger2Activity extends AppCompatActivity implements ActivityDataProvider { @Inject ActivityObj mActivityObj; @Inject FragmentNotVisibleObj mActivityNotVisibleObj; @Inject ActivityScopeObj mActivityScopeObj; ActivityComponent component = DaggerActivityComponent.builder() .activityModule(new ActivityModule()) .build(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_dagger2_test); // 使用component來給Dagger2Activity的屬性賦值 component.inject(this);
再看看ActivityComponent生命的inject方法
public interface ActivityComponent { void inject(Dagger2Activity dagger2Activity);
案例地址:dagger案例源碼
// BigScope @Documented @Scope @Retention(RetentionPolicy.RUNTIME) public @interface BigScoped { } // SmallScope @Documented @Scope @Retention(RetentionPolicy.RUNTIME) public @interface SmallScoped { }
(1)Dagger2Activity
public class Dagger2Activity extends AppCompatActivity implements ActivityDataProvider { @Inject ActivityObj mActivityObj; @Inject FragmentNotVisibleObj mActivityNotVisibleObj; @Inject ActivityScopeObj mActivityScopeObj; ActivityComponent component = DaggerActivityComponent.builder() .activityModule(new ActivityModule()) .build(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_dagger2_test); // 使用component來給Dagger2Activity的屬性賦值 component.inject(this); Dagger2Fragment dagger2Fragment = new Dagger2Fragment(); dagger2Fragment.setDataProvider(this); getFragmentManager().beginTransaction() .addToBackStack(null) .replace(R.id.container, dagger2Fragment) .commit(); } @Override public ActivityComponent getComponent() { return component; } @Override public ActivityScopeObj getActivityScopeObj() { return mActivityScopeObj; } }
(2)ActivityComponent
@BigScoped @Component(modules = {ActivityModule.class},dependencies = {AppComponent.class}) public interface ActivityComponent { // 暴露接口給Dagger2Activity,讓其傳入本身,好給Dagger2Activity屬性賦值 void inject(Dagger2Activity dagger2Activity); // 暴露給其餘Component的接口,只有暴露的接口,其餘的Component才能夠依賴於它建立對象,按照返回類型匹配,與函數名無關 ActivityScopeObj activityScopeObj(); ActivityObj activityObj(); }
(3)ActivityModule
@Module public class ActivityModule { @Provides public ActivityObj provideActivityObj() { return new ActivityObj(); } @Provides public FragmentNotVisibleObj provideActivityNotVisibleObj() { return new FragmentNotVisibleObj(); } @BigScoped @Provides public ActivityScopeObj provideActivityScopeObj() { return new ActivityScopeObj(); } }
【Dagger2Activity的總體注入過程以下圖】
從圖中能夠看出dagger2的實現模型和上面介紹的Ioc控制反轉模型表現一致
(1)Dagger2Fragment
須要注入三個對象
- mActivityObj由ActivityComponent生成 - mActivityScopeObj由ActivityComponent生成 - mFragmentObj有FragmentComponent生成 - 其餘參見注釋
public class Dagger2Fragment extends android.app.Fragment { ActivityDataProvider mProvider; @Inject ActivityObj mActivityObj; @Inject ActivityScopeObj mActivityScopeObj; @Inject FragmentObj mFragmentObj; @Override public View onCreateView(LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.dagger2_fragment, container, false); FragmentComponent component = DaggerFragmentComponent.builder() .fragmentModule(new FragmentModule()) // 依賴於ActivityComponent,是由Activity傳進來的,所以次數使用的activityComponent和Dagger2Activity使用的Component是同一個對象 // 所以 mActivityScopeObj和mProvider.getActivityScopeObj()獲得的是同一個對象 .activityComponent(mProvider.getComponent()) .build(); component.inject(this); // true Logger.d("ActivityScope single instance:" + (mActivityScopeObj == mProvider.getActivityScopeObj())); // false Logger.d("not Scope Object:" + (mActivityObj == mFragmentObj.mActivityObj)); return view; } public void setDataProvider(ActivityDataProvider provider) { mProvider = provider; } }
(2)FragmentComponent
@Component(modules = {FragmentModule.class},dependencies = {ActivityComponent.class}) @SmallScoped public interface FragmentComponent { void inject(Dagger2Fragment dagger2Fragment); }
(3)FragmentObj
public class FragmentObj { @Inject ActivityObj mActivityObj; // 用@Inject修飾構造和在Module用@Provide修飾等價 @Inject public FragmentObj() { } }
(1)查找對象按照什麼匹配?
按照類型匹配
@Module public class ActivityModule { @Provides public ActivityObj provideActivityObj() { return new ActivityObj(); } @Provides public ActivityObj ActivityObj() { return new ActivityObj(); }
(2)Scope之間的依賴關係怎麼肯定?
按照其修飾的Component間的依賴關係決定,仍是上面的例子:
@Component(modules = {FragmentModule.class},dependencies = {ActivityComponent.class}) @SmallScoped public interface FragmentComponent { void inject(Dagger2Fragment dagger2Fragment); } @BigScoped @Component(modules = {ActivityModule.class},dependencies = {AppComponent.class}) public interface ActivityComponent { void inject(Dagger2Activity dagger2Activity); ActivityScopeObj activityScopeObj(); ActivityObj activityObj(); }
由於FragmentComponent-->ActivityComponent。所以,能夠得出ActivityComponent實例生命週期長於FragmentComponent的實例(否則,FragmentComponent要傳入AppComponent依賴的時候,沒有能夠賦的值),所以能夠得出SmallScope和BiggerScope之間存在以下關係。
<img src="https://img-blog.csdn.net/201...; width="70%">
(3)其餘更多工程上使用的問題能夠參見ppt:dagger2源碼分析