Dagger2

(個人學習筆記)

作用:對象的管理,降低程序耦合。

框架類型:Dagger2是一個依賴注入框架。

性能:Dagger2的註解框架採用的是apt代碼自動生成技術,註解停留在編譯階段,所以說不影響性能。

主要常用標識:@Inject,@Component,@Module,@Provides,@SubComponent,@SingleTon,modules,dependiences。

*ButterKnife也是一種註解框架,採用的也是apt代碼自動生成技術。

看了很多次Dagger2,但是從入門到放棄N多次。下面來總結一下Dagger2的一些用法,現在Dagger2,Annotation,ButterKnife這種註解。

首先我們來看下面這張關係圖。這就是Dagger2的使用模式。通過一個@componet這個橋樑,我們大大的提升了程序的解耦性。

假設有6,7個地方需要使用A.class對象。但此時A對象的構造數,增加或減少一個或者N個參數。以往的做法,我們會挨個兒在new了A.class的地方去修改對象。但現在我們只需要修改A.class本身就好了。*不同的情況,改變的位置也不盡相同

 

根據上面這張關係圖,來一份無參的案例。(主要是對@Inject,@Componet 註解的使用)

1.A.class類

public class NoParam {
    @Inject
    public NoParam() {
    }
}

2.B.interface

@Component
public interface NoParamComponet {
    //指定要注入的目標NoParamActivity 
    void inject(NoParamActivity noParamActivity);
}

3.C.Activity 值得注意的是:@Inject的對象不可用private修飾,要用public或者protect。

public class NoParamActivity extends Activity {

    @Inject
    protected NoParam noParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_doublewave);
        //觸發dagger注入機制
        DaggerNoParamComponet.create().inject(this);
        Toast.makeText(this, "結果="+noParam.hashCode(), Toast.LENGTH_SHORT).show();
    }
}

有參數的案例

1.參數對象一InsiceParam

public class InsideParam {
    @Inject
    public InsideParam() {
    }
}

2.參數對象二HaveParam。包含參數一

public class HaveParam {
    @Inject
    protected InsideParam insideParam;

    public HaveParam(InsideParam insideParam) {
        this.insideParam = insideParam;
    }
}

3.B.interface(Component對象)

@Component
public interface HaveParamComponet {
    void inject(HaveParamActivity haveParamActivity);
}

4.C.activity(調用對象)

public class HaveParamActivity extends Activity {

    @Inject
    protected HaveParam haveParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_dagger_student);
        DaggerHaveParamComponet.create().inject(this);
        Toast.makeText(this,"結果="+haveParam.hashCode()+
                haveParam.insideParam.hashCode(),Toast.LENGTH_LONG).show();
    }
}

這裏有一點值得注意,在HaveParam裏面的時候,並沒有對InsideParam做create().inject()的操作來完成注入。那到底是誰幫我們把InsideParam完成操作了呢?

答案:是HaveParamActivity對InsideParam完成了注入操作。

解釋:在HaveParamActivity裏面,在進行inject對象HaveParam的時候發現HaveParam的構造函數被inject標註,且帶有一個參數,於是Dagger2去尋找InsideParam,它的構造參數被@Inject標註且無參數。於是Dagger2把InsideParam注入給HaveParamActivity。再去實例化的時候用的是已經注入給HaveParamActivity的那個InsideParam實例。

分析結果:HaveParamActivity將InsideParam實例化,將實例化後的InsideParam拿去給HaveParam使用。

調用第三方類庫對象

上面是我們自己定義的對象類,那如何調用第三方類庫的對象?(主要是@Module,@Provides的使用)

案例如下:

1.HttpModule(這裏使用了@Module和@Provides。)

@Module的作用:我們需要注入的類是第三方類庫,我們無法再構造函數直接加@Inject註解,還有一個問題就是如果有多個構造函數的問題,Module封裝依賴就是爲了解決這些問題。

@Provides作用:標註@Module中能夠提供實例化的方法。

@Module
public class HttpMudule {

    @Provides
    OkHttpClient providerHttpClient(){
        return new OkHttpClient();
    }
}

2.Component

使用@Component標註這個接口,並使用modules=的方法鏈接上第一步中編寫的Module類(連接HttpMudule類);

@Component(modules = HttpMudule.class)
public interface HttpModuleComponet {
    void inject(HttpActivity httpActivity);
}

3.HttpActivity

public class HttpActivity extends Activity {

    @Inject
    protected HttpMudule httpMudule;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        setContentView(R.layout.layout_doublewave);
        DaggerHttpModuleComponet.create().inject(this);
        Toast.makeText(this, "結果="+httpMudule.hashCode(), Toast.LENGTH_SHORT).show();
    }
}

Module中的@Provides含參,且參數依賴另外的@Provides返回值

先邏輯分析這個過程:

第一步:在Module內尋找,@Provides方法返回值=含有參數的@Provides的參數值。

第二步:如果第一步中沒有在Module中找到那個返回值的@Provides方法。則去看這個類的構造函數是否被@Inject標註

由此可得:一般情況下,Module中方法返回值都不能相同。但有辦法使其返回值相同。

案例如下:

@Module
public class HttpMudule {

    private int num;

    public HttpMudule(int num) {
        this.num=num;
    }


    @Provides
    OkHttpClient providerHttpClient(int num){
        OkHttpClient okHttpClient=new OkHttpClient();
        okHttpClient.setTimeSize(this.num);
        return okHttpClient;
    }

    @Provides
    RetrofitDemo providerRetrofit(OkHttpClient okHttpClient){
        return new RetrofitDemo(okHttpClient);
    }

}

 HttpActivity的Componet注入則修改爲如下寫法,動態輸入參數num=200。 

public class HttpActivity extends Activity {

    @Inject
    protected HttpMudule httpMudule;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        setContentView(R.layout.layout_doublewave);
        //DaggerHttpModuleComponet.create().inject(this);//之前的寫法
        DaggerHttpModuleComponet.builder().httpMudule(new HttpMudule(200)).build().inject(this);//@Module依賴另外的依賴之後的寫法(不一定全是這樣寫)。
        Toast.makeText(this, "結果="+httpMudule.hashCode(), Toast.LENGTH_SHORT).show();
    }
}

Component和Component之間的依賴關係的實現

類和類之間的依賴有extends來實現,component和Component的依賴由DependencesubComponent來實現。

1.dependence

邏輯:A.class  B.class  AComponent(父)  BComponent(子)  AActivity  BActivity

在BComponent中加入dependencies來表明依賴於AComponent。

在AActivity裏面增加一個方法,返回結果爲AComponent對象的方法getAComponent()。

在BActivity裏面注入之前,new一個AComponent,對象=AActivity.getAComponent();

在BActivity注入的時候,用build,可以注入Acommponent。從而使用AComponent的注入,完成依賴。

2.subComponent(wasabi的Part 0...   0...

HttpFragmentComponent是子。HttpActivityComponent是父。

a.在子Component中加入@Subcomponent標識

b.在父Component中獲得定義子Component的方法。

c.在子Activity注入的時候,Component實例化。

Scope作用域---單例

a.無Module的使用方式。

@Singleton
public class HttpMudule {
    OkHttpClient providerHttpClient(){
        return new OkHttpClient();
    }
}
@Singleton
@Component
public interface HttpModuleComponet {
    void inject(HttpActivity httpActivity);
}

Actvity和之前的一樣。就不po了。

結果分析:@Singleton不可以標註構造器。依賴類標註了@Singleton,那麼Component也要標註@Singleton。否則會報錯。

b.帶module的使用方式。

@Module
public class HttpMudule {
    @Singleton
    @Provides
    OkHttpClient providerHttpClient(){
        return new OkHttpClient();
    }
}
@Singleton
@Component(modules = HttpMudule.class)
public interface HttpModuleComponet {
    void inject(HttpActivity httpActivity);
}

其他和上面一樣。

結果分析:@Module內的@Provides需要被標註@Singleton。Component需要被標註上@Singleton

對於@Scope的總結:

在某個範圍裏它是單例(何爲作用域呢,可以看作是我們在程序中實例化的Component的生命週期的長短:如果在Application裏build的那它的作用域就是整個App的生命週期,如果是在Acitivity中build的那它的作用域就跟此Acitivity的生命週期相同,依次類推)。

後續補充......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章