Dagger2學(xué)習(xí)筆記1(基礎(chǔ)概念學(xué)習(xí))
Dagger2學(xué)習(xí)筆記2(學(xué)習(xí)Dagger2的簡(jiǎn)單使用)
Dagger2學(xué)習(xí)筆記3(各個(gè)注解學(xué)習(xí))
上篇文章中學(xué)習(xí)了Dagger2中各個(gè)注解的作用及如何使用, 其中涉及到兩個(gè)特殊的注解, @Singleton 和@ Scope, 接下來(lái)我們將學(xué)習(xí)怎么使用它們做到全局單例.
上篇文章我們學(xué)習(xí)到Singleton是繼承自Scope, 所以可以看做是Scope的代表實(shí)現(xiàn). Scope的作用是保證依賴對(duì)象在作用范圍內(nèi)單例, 提供局部范圍的單例,所謂局部范圍就是它的生命周期范圍
舉個(gè)栗子:
public class Dog {
private String name;
public Dog(String name){
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}' + "hashcode = "+hashCode();
}
}
@Module
public class MainModule {
@Provides
Dog provideDog(){
return new Dog("bob");
}
}
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(MainActivity mainActivity);
}
public class MainActivity extends AppCompatActivity {
@Inject
Dog dog1;
@Inject
Dog dog2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);
((TextView)findViewById(R.id.tv1)).setText(dog1.toString());
((TextView)findViewById(R.id.tv2)).setText(dog2.toString());
}
}
以上代碼中, 沒(méi)有使用@Singleton 修飾, 在MainActivity 中對(duì) Dog進(jìn)行兩次依賴注入, 查看輸出結(jié)果

可以看出得到的是兩個(gè)Dog對(duì)象, 也就是每依賴注入一次都會(huì)從新調(diào)用一次provideDog方法.
接下來(lái)我們使用@Singleton注解進(jìn)行. 修改其中部分代碼(Module的依賴提供方法上以及Component的類名上)
@Module
public class MainModule {
@Singleton
@Provides
Dog provideDog(){
return new Dog("bob");
}
}
@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(MainActivity mainActivity);
}
運(yùn)行結(jié)果如下:

我們可以看到兩個(gè)對(duì)象輸出的hash值相同, 已經(jīng)實(shí)現(xiàn)了一部分的單例, but, 你以為這就實(shí)現(xiàn)了全局單例了么? 我們?cè)賹懸粋€(gè)新的頁(yè)面測(cè)試下!
public class SecondActivity extends AppCompatActivity {
@Inject
Dog dog1;
@Inject
Dog dog2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
DaggerMainComponent.builder().mainModule(new MainModule()).build().inject(this);
((TextView)findViewById(R.id.tv1)).setText(dog1.toString());
((TextView)findViewById(R.id.tv2)).setText(dog2.toString());
}
}

我們發(fā)現(xiàn), 雖然provideDog使用@Singleton注解, 但是在不同的頁(yè)面,拿到的依賴對(duì)象仍然不是同一個(gè), 這也就是我們之說(shuō)的局部范圍的單例, 使用@Singeton注解或者定制的@Scope的, 只在同一個(gè)activity(或者fragment)的一個(gè)生命周期中保持單例. 而平時(shí)我們希望一些對(duì)象能夠在整個(gè)應(yīng)用的生命周期中只存在一個(gè), 也就是說(shuō)實(shí)現(xiàn)全局意義上真正的單例該怎么做呢?
DaggerMainComponent在兩個(gè)activity中被各自被實(shí)例化一次, 導(dǎo)致產(chǎn)生了兩個(gè)不同的對(duì)象, 所以我們需要做到讓Component能夠?qū)崿F(xiàn)單例, Android中, 我們知道在整個(gè)App生命周期中都只有一個(gè)Appclication實(shí)例,所以在Application中獲得一個(gè)唯一的component實(shí)例, 用它來(lái)提供我們需要的單例:
代碼如下:
- 自定義Application, 并且提供一個(gè)唯一的baseComponent類
public class BaseAppclication extends Application {
private BaseComponent baseComponent;
@Override
public void onCreate() {
super.onCreate();
baseComponent = DaggerBaseComponent.builder().baseModule(new BaseModule()).build();
}
public BaseComponent getBaseComponent(){
return baseComponent;
}
}
- 把dog類的依賴提供提取到BaseModule中
@Module
public class BaseModule {
@Singleton
@Provides
Dog provideDog(){
return new Dog("bob");
}
}
- BaseComponent中不再需要寫inject方法, 因?yàn)檫@個(gè)component是用來(lái)讓別的component來(lái)依賴的, 只需要告訴別的component他可以提供哪些類型的依賴即可, 這個(gè)例子中 我們提供一個(gè)全局Dog的依賴
@Singleton
@Component(modules = BaseModule.class)
public interface BaseComponent {
Dog provideDog();
}
- 在我們自己的Component, 使用dependencies依賴于baseComponent, (在@Component注解參數(shù)中, 可以依賴多個(gè)module和component, 根據(jù)自己的業(yè)務(wù)需求定義即可.)
@ActivityScope
@Component(dependencies = BaseComponent.class)
public interface MainComponent {
void inject(MainActivity mainActivity);
void inject(SecondActivity mainActivity);
}
這一步需要注意的是, 這個(gè)component也需要進(jìn)行單例修飾, 但是當(dāng)我們使用@Singleton注解時(shí), 編譯會(huì)報(bào)一個(gè)Error:(14, 1) 錯(cuò)誤: This @Singleton component cannot depend on scoped components, 如果依賴的component中也使用了@singleton時(shí), 被依賴的地方就不能使用了,于是我自定義了一個(gè)Scope: ActivityScope
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
好了, 現(xiàn)在準(zhǔn)備工作都做好了, 在頁(yè)面中重新進(jìn)行依賴注入工作,
public class MainActivity extends AppCompatActivity {
@Inject
Dog dog1;
@Inject
Dog dog2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder().baseComponent(((BaseAppclication)getApplication()).getBaseComponent()).build().inject(this);
((TextView)findViewById(R.id.tv1)).setText(dog1.toString());
((TextView)findViewById(R.id.tv2)).setText(dog2.toString());
}
public void click(View v){
startActivity(new Intent(this, SecondActivity.class));
}
}
這個(gè)Component在build的時(shí)候需要提供依賴的baseComponent, 此時(shí)我們使用已經(jīng)在baseApplication中已經(jīng)提供的唯一的baseModule, SecondActivity中代碼和上邊差不多, 不貼了. 運(yùn)行查看結(jié)果:

哈哈, 我們發(fā)現(xiàn)已經(jīng)成功的實(shí)現(xiàn)了單例!!
下篇文章中會(huì)寫到關(guān)于Lazy和Provider的使用.
Dagger2學(xué)習(xí)筆記5(關(guān)于Lazy,Provide的使用)
本文至此, End!~~