Android Dagger (二) Provides 、Lazy、Qualifier、Scope 等
阿新 • • 發佈:2019-02-14
@Provides
上文其實已經講到,這裡重複一下概念
@Provides 可以認為是 @ibject的補充,比如我們使用 OkHttp庫 其他第三庫時,我們並無法直接注入
每定義一個方法,都將生成 獨立的 .java檔案
比如下面程式碼:
- 生成檔案列表
– DemoModule_ProvidePerson1Factory.java
– DemoModule_ProvidePerson2Factory.java
– DemoModule_ProvidePerson3Factory.java
@Module
public class DemoModule {
@Provides
Person providePerson1(){
return new Person();
}
@Provides
Person providePerson2(){
return new Person();
}
@Provides
Person providePerson3(){
return new Person();
}
}
Lazy
延遲注入,其實與 kotlin的 lazy 相同概念
只有在呼叫 Lazy 的 get() 方法時才會初始化依賴例項注入依賴
public class Person {
@Inject
Lazy<Car> lazyCar;
public void goWork() {
...
lazyCar.get().go(); // lazyCar.get() 返回 Car 例項
...
}
}
Qualifier
上面的 DemoModule 提供了三個方法 但是都返回了 Person,
那 dagger 怎麼知道我們要使用哪個返回的Person呢? 在編譯時就會報錯
網上說法,叫依賴迷失, 那如何解決,主人公 Qualifier就派上用場了
module
@Module
public class DemoModule {
@Provides
@Named("person1")
Person providePerson1(){
return new Person();
}
.. 以此類推
}
component
@Component(modules = DemoModule.class)
public interface DemoCompoent {
void inject(DemoActivity activity);
}
activity
public class DemoActivity extends AppCompatActivity {
@Inject
@Named("person1")
Person person;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
DaggerDemoCompoent.create().inject(this);
// 搞定
((TextView)findViewById(R.id.tv_content)).setText(String.valueOf(person.hashCode()));
}
}
Scope <作用域>
Scope 是用來確定注入的例項的生命週期的,如果沒有使用 Scope 註解,Component 每次呼叫 Module 中的 provide 方法或 Inject 建構函式生成的工廠時都會建立一個新的例項
我們先來設想下這樣的場景
顯然如果我們不做任何處理 @Inject注入,每個人都會有一輛車。
那麼如何避免? Scope 來了~
定義物件
public class Wang {
Car car;
public Wang(Car car) {
this.car = car;
System.out.println("我是王 我的車子物件是 -> " + car.hashCode());
}
}
public class Zhang {
Car car;
public Zhang(Car car) {
this.car = car;
System.out.println("我是張 我的車子物件是 -> " + car.hashCode());
}
}
scope
固定格式,主要是名字 跟 使用位置區分
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface CarScope {}
module
@Module
public class CarModule {
@Provides
@CarScope // 自定義作用域,可以嘗試註釋掉,然後最後輸出就變為了三個car
Car provideCar(){
return new Car();
}
}
@Module
public class DemoModule {
@Provides
Zhang provideZhang(Car car){
return new Zhang(car);
}
@Provides
Wang provideWang(Car car){
return new Wang(car);
}
}
DemoComponent
@Component(modules = {
CarModule.class,
DemoModule.class
})
@CarScope // 必須與 module provide限制相同,否則編譯不通過
public interface DemoComponent {
void inject(DemoActivity activity);
}
Activity使用
public class DemoActivity extends AppCompatActivity {
@Inject
Zhang zhang;
@Inject
Wang wang;
@Inject
Car car;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
DaggerDemoComponent.create().inject(this);
System.out.println("car --> " + car.hashCode());
}
}
// 輸出結果
我是張 我的車子物件是 -> 237250545
我是王 我的車子物件是 -> 237250545
car --> 245728614
這樣也就確保了,只有一輛車