Android:dagger2讓你愛不釋手-基礎(chǔ)依賴注入框架篇
Android:dagger2讓你愛不釋手-重點概念講解敏晤、融合篇
Android:dagger2讓你愛不釋手-終結(jié)篇
Dagger 2 完全解析(一)嗡载,Dagger 2 的基本使用與原理
Dagger 2 完全解析(二),進階使用 Lazy麻车、Qualifier临梗、Scope 等
Dagger 2 完全解析(三)蠢沿,Component 的組織關(guān)系與 SubComponent
Dagger 2 完全解析(四)肩榕,Android 中使用 Dagger 2
Dagger 2 完全解析(五)垮抗,Kotlin 中使用 Dagger 2
Dagger 2 完全解析(六)氏捞,dagger.android 擴展庫的使用
1、Component的使用
作為橋連接依賴和被依賴對象冒版。
每一個Component都會創(chuàng)建一個對應(yīng)的DaggerComponent
@Inject注解的構(gòu)造函數(shù)會創(chuàng)建對應(yīng)類的Factory液茎,用于實例化該類
/**
* 藥物
*/
public class Medicine {
@Inject
public Medicine() {
}
public void treat() {
LogUtil.e("開始治療");
}
}
/**
* 注射器
*/
@Component
public interface Injector {
//注射動作,指定病患
void inject(MainActivity mainActivity);
}
/**
* 病患
*/
public class MainActivity extends AppCompatActivity {
@Inject
Medicine mMedicine;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//口服
Medicine medicine = new Medicine();
medicine.treat();
//打針
DaggerInjector.create().inject(this);
mMedicine.treat();
}
}
2辞嗡、Module使用場景
1捆等、沒有構(gòu)造函數(shù)
2、有參構(gòu)造
3续室、三方庫的類
每一個@Provides注解的方法都會創(chuàng)建一個Factory用來提供實例化對象給DaggerComponent使用栋烤。
@Provides注解的方法所需要的參數(shù)會優(yōu)先從Module的其他provide中取。
@Module
public class ModuleClass {
@Provides
Gson provideGson() {
return new Gson();
}
}
@Component(modules = ModuleClass.class)
public interface ComponentClass {
void inject(MainActivity2 mainActivity);
}
public class MainActivity2 extends AppCompatActivity {
@Inject
Gson mGson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerComponentClass.create().inject(this);
String s = mGson.toJson(new Medicine());
LogUtil.e(s);
}
}
3挺狰、@Scope作用域
@Scope是一個元注解明郭,用于注解自定義注解买窟,可以確定注入的實例的生命周期,并在聲明周期內(nèi)保持實例唯一达址。使用時Module 中 provide 方法中的 Scope 注解必須和 與之綁定的 Component 的 Scope 注解必須一樣蔑祟,否則作用域不同會導(dǎo)致編譯時會報錯。
作用域的原理沉唠,其實是讓生成的依賴實例的生命周期與 Component 綁定疆虚,Scope 注解并不能保證生命周期,要想保證賴實例的生命周期满葛,需要確保 Component 的生命周期径簿。
@Singleton是通過@Scope定義的一個新的注解,能夠使同一個Component中的對象保持唯一嘀韧,保持唯一的條件是通過@Scope標(biāo)記的注解相同篇亭。
@Singleton并沒有創(chuàng)建單例的能力,起作用為
1锄贷、保證Component和Module是匹配的译蒂。
2、代碼可讀性谊却。
以頁面劃分component柔昼,一個頁面一個component,但這并不是一定的炎辨,有時候多頁面會共用一個component捕透,因為它們需要的參數(shù)一致。
一個全局component用來管理管理整個App的全局類實例碴萧。
@Scope //注明是Scope
@Documented //標(biāo)記在文檔
@Retention(RUNTIME) // 運行時級別
public @interface Singleton {}
@Module
public class FactoryModule {
@Provides
Gson provideGson() {
LogUtil.e("創(chuàng)建Gson對象");
return new Gson();
}
}
@Component(modules = FactoryModule.class)
public interface BridgeComponent {
Gson getGson();
}
public class App extends Application {
public static BridgeComponent sBridgeComponent;
@Override
public void onCreate() {
super.onCreate();
sBridgeComponent = DaggerBridgeComponent.create();
}
}
@Module
public class ActivityModule {
@Singleton
@Provides
Person5 providesPersonWithString() {
return new Person5("xls");
}
}
@Singleton
@Component(dependencies = BridgeComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
void inject(MainActivity3 mainActivity);
}
public class MainActivity3 extends AppCompatActivity {
@Inject
Person5 mPerson5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder().bridgeComponent(App.sBridgeComponent).activityModule(new ActivityModule()).build().inject(this);
Gson gson = App.sBridgeComponent.getGson();
LogUtil.e(gson.toJson(mPerson5));
}
}
4乙嘀、有參構(gòu)造
MainModule -->providesPerson()中new Person(context)不能直接使用this.context,Module中查找返回Context的方法破喻,并注入虎谢。此場景默認(rèn)調(diào)用providesContext方法獲取context。
public class Person {
public String name = "張三";
public int age = 23;
private Context context;
public Person(Context context) {
LogUtil.e("a person created with context:" + context);
}
}
@Module
public class MainModule {
private Context context;
public MainModule(Context context) {
this.context = context;
}
@Provides
public Context providesContext() {
return this.context;
}
@Provides
public Person providesPerson(Context context) {
LogUtil.e("person from module");
return new Person(context);
}
}
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(MainActivity4 mainActivity4);
}
public class MainActivity4 extends AppCompatActivity {
@Inject
Person mPerson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder().mainModule(new MainModule(getApplicationContext())).build().inject(this);
String s = App.getInstance().mGson.toJson(mPerson);
LogUtil.e(s);
}
}
5曹质、自定義標(biāo)記婴噩、限定符
用于區(qū)分同類的不同依賴
public class Person5 {
public String name = "張三";
public int age = 23;
public Context context;
public Person5(Context context) {
this.context = context;
LogUtil.e("a person created with context:" + context);
}
public Person5(String name) {
this.name = name;
LogUtil.e("a person created with name:" + name);
}
}
@Module
public class MainModule5 {
private Context context;
public MainModule5(Context context) {
this.context = context;
}
@Provides
public Context providesContext() {
return this.context;
}
// @Named("context")
@PersonForContext
@Provides
public Person5 providesPersonWithContext(Context context) {
return new Person5(context);
}
// @Named("string")
@PersonForName
@Provides
public Person5 providesPersonWithName() {
return new Person5("yxm");
}
}
@Component(modules = MainModule5.class)
public interface MainComponent5 {
void inject(MainActivity5 mainActivity5);
}
public class MainActivity5 extends AppCompatActivity {
// @Named("string")
@PersonForName
@Inject
Person5 p1;
// @Named("context")
@PersonForContext
@Inject
Person5 p2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent5.builder().mainModule5(new MainModule5(getApplicationContext())).build().inject(this);
String s1 = App.getInstance().mGson.toJson(p1);
LogUtil.e(s1);
//java.lang.SecurityException: Can not make a java.lang.reflect.Method constructor accessible
// String s2 = App.getInstance().mGson.toJson(p2);
// LogUtil.e(s2);
}
}
@Qualifier // 關(guān)鍵詞
@Retention(RetentionPolicy.RUNTIME) // 運行時仍可用
public @interface PersonForContext {
// Context 對象的注解
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PersonForName {
// name 對象的注解
}
6、Provider咆繁、Lazy
沿用demo5部分文件
@Module
public class MainModule5 {
private Context context;
public MainModule5(Context context) {
this.context = context;
}
@Provides
public Context providesContext() {
return this.context;
}
// @Named("context")
@PersonForContext
@Provides
public Person5 providesPersonWithContext(Context context) {
return new Person5(context);
}
// @Named("string")
@PersonForName
@Singleton
@Provides
public Person5 providesPersonWithName() {
return new Person5("yxm");
}
}
@Singleton
@Component(modules = MainModule5.class)
public interface MainComponent5 {
void inject(MainActivity5 mainActivity5);
}
public class MainActivity5 extends AppCompatActivity {
// @Named("string")
@PersonForName
@Inject
Person5 p1;
@PersonForName
@Inject
Provider<Person5> providerPerson;
// @Named("context")
@PersonForContext
@Inject
Lazy<Person5> lazyPerson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent5.builder().mainModule5(new MainModule5(getApplicationContext())).build().inject(this);
Person5 person5 = lazyPerson.get();// 調(diào)用該方法時才會去創(chuàng)建Person,以后每次調(diào)用獲取的是同一個對象
Person5 person6 = lazyPerson.get();
Person5 person7 = providerPerson.get();// 調(diào)用該方法時才回去創(chuàng)建Person1,以后每次調(diào)用都會重新加載Module中的具體方法顶籽,根據(jù)Module中的實現(xiàn)玩般,可能相同,可能不相同礼饱。加@Singletom注解坏为,創(chuàng)建一次
Person5 person8 = providerPerson.get();
String s1 = App.getInstance().mGson.toJson(p1);
LogUtil.e(s1);
//java.lang.SecurityException: Can not make a java.lang.reflect.Method constructor accessible
// String s2 = App.getInstance().mGson.toJson(p2);
// LogUtil.e(s2);
}
}
總結(jié)
1究驴、將實例化操作抽離出來,達到解耦的效果
2匀伏、單例無需考慮線程是否安全