編輯:關於android開發
(這篇博客真是磨難重重啊,寫到一半電腦藍屏了,還好markdown編輯器保持了部分類容)
最近開始重構項目,在重構項目中用到了依賴注入框架dagger2,發現它確實很方便,能大大加快我們編寫代碼的速度,同時也很方便我們對於功能模塊的解耦。在這裡就不過多介紹dagger2了,大家谷歌 百度一下就能得到很多關於dagger2的介紹。學習dagger2是需要一定的學習成本的,我自己開始學習的時候也差不多花了一周的時間才弄明白怎樣使用dagger2,下面就說說自己對dagger2的理解和使用方法。
dagger2中最重要的就是module和component了,module是生產我們需要的對象的地方,component是聯系module和module生產出的對象的使用場景的橋梁。(說白了,dagger2就像是設計模式中的工廠模式,為我們生產各種我們需要的對象)
不明白?上代碼:(假如我們有一個類A,然後我們通過依賴注入方法要在MainActivity中使用)
×××××××××××××××××××××××不使用dagger2××××××××××××××××××××××××
//類A
public class A {
private int field;
... //其他屬性
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//類MainActivity
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
A a=new A();
a.doSomething();
a.doOtherthing();
}
}
×××××××××××××××××××××××使用dagger2××××××××××××××××××××××××
//類A
public class A {
private int field;
... //其他屬性
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//我們先要構造一個Module,這個Module中生產A的對象
@Module
public class AMedule {
@Provides
A provideA(){
return new A();
}
}
//然後需要一個Component,用了連接Module和MainActivity
@Component(modules = AMedule.class)
public interface ActivityComponent {
A a();
}
//在MainActivity類中使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityComponent component=DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build();
A a=component.a();
a.doSomething();
a.doOtherthing();
}
}
一個簡單的依賴注入就完成了。也許大家會覺得這樣寫很麻煩,其實不然,還有一種更加簡單的方法來做這件事,我們把B注入到BComponent中,直接使用@Inject注解:
//類A
public class A {
private int field;
... //其他屬性
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//我們先要構造一個Module
@Module
public class AMedule {
@Provides
A provideA(){
return new A();
}
}
//然後需要一個Component
@Component(modules = AMedule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
//在MainActivity類中使用
public class MainActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build()
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
怎麼樣,是不是簡單,方便一些了。什麼?還麻煩,那我們更進一步吧(由於這裡的A類是我們自己定義的,可以更進一步):
//類A
public class A {
private int field;
... //其他屬性
@Inject
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//我們先要構造一個Module(其實這裡Module已經用不到了,我們不需要通過Modu生產A了,不過為了與上面對比,還是留著吧)
@Module
public class AMedule {
// @Provides
// A provideA(){
// return new A();
// }
}
//然後需要一個Component
@Component(modules = AMedule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
//在MainActivity類中使用
public class MainActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build()
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
是不是看迷糊了,A沒有在Module生產,那是怎麼來的呢?不知道大家注意到沒有,A的構造方法上面有個@Inject注解,沒錯,就是他,就是這個注解生產A對象的。
看到這裡,我們就知道dagger2生產對象有兩種方式,一種是在Module中通過@Provides注解加上providexxx 方法,另一種就是直接在要生產的對象的類的構造方法加上@inject注解。
在這裡悄悄告訴大家: 一般生成系統或者SDK或者第三方庫提供的類的對象時用Module,而自定義的類的對象用@Inject,當然,你也可以用一個類繼承系統或者SDK或者第三方庫提供的類,然後在其構造方法加上@Inject注解。
2. 可能大家對Module和Component的還是似懂非懂,在這裡在打一個形象一點的比喻吧。
例如到吃飯的時間了,我們要去做飯(吃外賣的繞道),我們得去廚房吧(希望不是野外燒烤),我們需要煤氣灶(也可能是電磁爐),鍋,刀,砧板,盆子….(發現需要的真多哈),這些都是一個個類吧,你廚房裡的那些具體的比如美的電飯煲(美的是不是得給點廣告費),蘇泊爾不粘鍋(剛買了一個)…..就是一個個具體的對象,我們有了這些具體的對象才能愉快的做飯,而Module就是讓我們得到這一個個對象(一個大工廠,生產美的電飯煲,蘇泊爾不粘鍋….),Component 就是我們的廚房,DaggerActivityComponent .builder().aMedule(new AMedule()).build() 就是讓我們擁有了一個廚房(想想機器貓的口袋,我們可以從裡面得到任何東西 ),我們可以從廚房裡面拿炊具做飯(往外拿:A a=component.a(),這是把廚房裡的東西拿到廚房外面,在外面做飯),而 DaggerActivityComponent.builder() .aMedule(new AMedule()) .build().inject(this)就是我們自己進入廚房,在廚房裡面 做飯(我們當然很容易獲得廚房裡面的炊具了,用@Inject獲得),好了,開始做飯。。。
3. 一個Component可以依賴多個Module,如
@Component(modules = {AModule.class,BModule.class,...})
@Component(dependencies = BComponent.class,modules = {AModule.class,BModule.class,...})
@Component(dependencies = {BComponent.class,CComponent.class,...}
,modules = {AModule.class,BModule.class,...})
//被依賴Component
@Component(modules = {...})
public interface BComponent {
A a();
B b();
}
//依賴Component
@Component(dependencies = BComponent.class,modules = {...})
public interface CComponent {
}
CComponent可以通過BComponent獲取A,B的對象,其他BComponent的對象對CComponent來說是透明的,不可見。
4. @Scope注解
這個注解是用來劃分作用域的(在哪兒使用),意思就是說我劃出一塊區域來,生產出的東西如果限定到此作用域都放到這裡,作用域的場景類(一般就是消費對象的地方,比如Activity)下次需要某個對象的時候,我就來這兒拿,如果有,就直接拿來用,如果沒有,就生產,並且放到這裡,同時自己用(有沒有一種方便自己,方便他人的感覺),dagger2自已有個@Scope注解,叫@Singleton,就是大家都熟悉的單例模式,你也可以自定義@Scope注解,比如限定生產出的某個對象只能在Activity中使用,只能在Application中使用,只能在Fragment中使用等等。。。
例如:我們寫一個限定作用域為Activity的Scope注解
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}
//類A
@PerActivity
public class A {
private int field;
... //其他屬性
@Inject
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//然後需要一個Component
@PerActivity
@Component()
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
//在MainActivity類中使用
public class MainActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.build()
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
//類A
public class A {
private int field;
... //其他屬性
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//我們先要構造一個Module
@Module
public class AMedule {
@PerActivity
@Provides
A provideA(){
return new A();
}
}
//然後需要一個Component
@PerActivity
@Component(modules = AMedule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
//在MainActivity類中使用
public class MainActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build()
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
假如我們還有一個SecondActivity也要使用A的對象
//類A
public class A {
private int field;
... //其他屬性
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//我們先要構造一個Module
@Module
public class AMedule {
@PerActivity
@Provides
A provideA(){
return new A();
}
}
//然後需要一個Component
@PerActivity
@Component(modules = AMedule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
void inject(SecondActivity secondActivity);
}
//在MainActivity類中使用
public class MainActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build()
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
//在SecondActivity類中使用
public class SecondActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build()
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
那麼,這裡MainActivity和SecondActivity中的A的對象a是同一個
5. 子Component
子Component跟前面的一個Component依賴另一個Component有點像,區別是子Component可以獲取到父Component的所有可以生產出的對象,而Component依賴則只能獲取到被依賴的Component所暴露出來的可以生產的對象。
//類A
public class A {
private int field;
... //其他屬性
public A() {
}
public void doSomething(){
Log.i("美女","我愛你");
}
public void doOtherthing(){
Log.i("美女","我是真的愛你");
}
... //其他方法
}
//我們先要構造一個Module
@Module
public class AMedule {
@Provides
A provideA(){
return new A();
}
}
//然後需要一個Component
@Component(modules = AMedule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
void inject(SecondActivity secondActivity);
}
//然後需要一個Component
@Component(modules = AMedule.class)
public interface BComponent {
void inject(MainActivity mainActivity);
CComponent plus(Module1 module1,Module2 module2,...);//參數為CComponent依賴的Module
}
//然後一個子Component(使用@Subcomponent注解)
@Subcomponent(modules = {...})
public interface CComponent {
void inject(SecondActivity secondActivity);
}
//在MainActivity類中使用,將MainActivity注入到父Component中
public class MainActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build()
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
//在SecondActivity類中使用,將SecondActivity注入到子Component中
public class SecondActivity extends AppCompatActivity {
@Inject
A a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.aMedule(new AMedule())
.build()
.plus(new Module1(),new Module2(),...)
.inject(this);
a.doSomething();
a.doOtherthing();
}
}
6.@Named注解
這個注解是用來設置別名的,用來區分同一個類型的不同對象。比如我們都知道Android 中的Context有兩種,一種是全局的,一種是Activity中的,為了區分他們,我們就可以加上別名;又比如有一個Person類,他有兩個實例,一個是小李,一個是小美,我們也可以用別名區分他們。
//Person類
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//我們先要構造一個Module
@Module
public class ActivityMedule {
@Named("小李")
@Provides
Person providePerson(){
return new Person("小李",18);
}
@Named("小美")
@Provides
Person providePerson(){
return new Person("小美",24);
}
}
//然後需要一個Component
@Component(modules = ActivityMedule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
//在MainActivity類中使用
public class MainActivity extends AppCompatActivity {
@Named("小李")
@Inject
Person p1;
@Named("小美")
@Inject
Person p2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder()
.activityMedule(new ActivityMedule())
.build()
.inject(this);
Log.i("person",p1.toString());
Log.i("person",p2.toString());
}
}
當然,如果你覺得@Named注解滿足不了你的需求,你也可以使用@Qualifier來自定義自己的別名注解
7.在android studio的使用
在build.gradle中添加依賴庫
compile 'com.google.dagger:dagger:2.2'
compile 'com.google.dagger:dagger-compiler:2.2'
provided 'org.glassfish:javax.annotation:10.0-b28'
好了,大概就講這麼多吧!
EventBus初理解,EventBus理解 緣由: 平時工作,因為懶於動筆的原因,也沒注重技術和經驗的積累,導致之前曾經研究過的問題現在又忘
Android 用Fragment創建一個選項卡,androidfragment本文結合之前的動態創建fragment來進行一個實踐,來實現用Fragment創建一個選項
Android之AlertDialog應用,androidalertdialogAndroid 中的對話框 dialog 對話框對於應用是必不可少的一個組件,在Andro
Android 手把手帶你玩轉自定義相機 概述 相機幾乎是每個APP都要用到的功能,萬一老板讓你定制相機方不方?反正我是有點方。關於相機的兩天奮斗總結免費送給你。 啟