国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Dagger2學(xué)習(xí)筆記之基本概念

2019-11-09 15:09:23
字體:
供稿:網(wǎng)友

看一個(gè)簡(jiǎn)單dagger2的Demo1

目標(biāo)類B

public class B {    @Inject    public B() {    }    public String getName(){        return "BBBBBBB";    }}頁面Activity

public class MainActivity extends BaseActivity {    @Inject    B b;    @Override    PRotected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //實(shí)例化component對(duì)象,注意DaggerBComponent是生成的,所以打這行代碼時(shí),先編譯一下        BComponent component = DaggerBComponent.builder().build();        //注入        component.injectB(this);        Log.e("-------","通過inject來實(shí)現(xiàn)======"+b.getName());    }}

@Componentpublic interface BComponent {    void injectB(Main2Activity activity);}

運(yùn)行,打印的結(jié)果為"通過...======BBBBBBB"

其中Inject注解(Annotation)來標(biāo)注目標(biāo)類中所依賴的其他類(MainActivity中的B),同樣用注解來標(biāo)注所依賴的其他類的構(gòu)造函數(shù)(B的構(gòu)造方法)

1:用Inject注解標(biāo)注目標(biāo)類中的其他類(MainActivity中的屬性B)

2:用Inject注解標(biāo)注其他類的構(gòu)造方法(B類的構(gòu)造方法)

3:用Inject注解標(biāo)注屬性時(shí),屬性不能用private修飾,不然會(huì)報(bào)錯(cuò),如下:

Error:(13, 20) 錯(cuò)誤: Dagger does not support injection into private fields

原因是Dagger2是采用編譯時(shí)產(chǎn)生注入代碼(一個(gè)注入工具類)來為變量注入值,注入過程如下所示:

public void injectMembers(MainActivity instance) {      if (instance == null) {      throw new NullPointerException("Cannot inject members into a null reference");    }    supertypeInjector.injectMembers(instance);    instance.str = strProvider.get();//為變量str注入值,若變量str為private,此處就無法引用到str}補(bǔ)充:inject還可以標(biāo)注在方法里,
使用@Inject注解提供依賴的方式是在這個(gè)類的public方法中作注解:
public class LoginActivityPresenter { private LoginActivity loginActivity; @Inject public LoginActivityPresenter(LoginActivity loginActivity) { this.loginActivity = loginActivity; } @Inject public void enableWatches(Watches watches) { watches.register(this); //Watches instance required fully constructed LoginActivityPresenter }}

方法的所有參數(shù)都是通過依賴圖表提供的。但是為什么我們需要方法注入呢?在某些情況下會(huì)用到,如當(dāng)我們希望傳入類的當(dāng)前實(shí)例(this引用)到被注入的依賴中。方法注入會(huì)在構(gòu)造器調(diào)用后馬上被調(diào)用,所以這表示我們可以傳入完全被構(gòu)造的this。因?yàn)閑nableWatches方法里需要用到LoginActivityPresenter對(duì)象實(shí)例,而用inject標(biāo)注這個(gè)方法的作用在于,當(dāng)這個(gè)構(gòu)造方法被調(diào)用時(shí),會(huì)把這個(gè)實(shí)例傳給watches.register(this)中去.

其中Component也是一個(gè)注解類,一個(gè)類要想是Component,

1:必須用Component注解來標(biāo)注該類

2:該類是接口或抽象類

3:方法名必須是injectXXX(Object),參數(shù)object是表示你要注入到哪里去,這里不能寫父類BaseActivity,因?yàn)榫唧w寫了哪個(gè)類,它就到哪個(gè)類中找Inject標(biāo)注的屬性

上文中提到Component在目標(biāo)類中所依賴的其他類與其他類的構(gòu)造函數(shù)之間可以起到一個(gè)橋梁的作用。

這個(gè)demo中component的工作原理是:

Component會(huì)查找MainActivity中用Inject注解標(biāo)注的屬性(B),查找到相應(yīng)的屬性后會(huì)接著查找該屬性(B)對(duì)應(yīng)的用Inject標(biāo)注的構(gòu)造函數(shù)(這時(shí)候就發(fā)生聯(lián)系了),剩下的工作就是初始化該屬性的實(shí)例并把實(shí)例進(jìn)行賦值。因此我們也可以給Component叫另外一個(gè)名字注入器(Injector)

Demo1還有種是對(duì)象B的構(gòu)造方法是由參數(shù)的,那么又應(yīng)該怎么弄呢?后面會(huì)有說明

引出Module類

項(xiàng)目中使用到了第三方的類庫(kù),第三方類庫(kù)又不能修改,所以根本不可能把Inject注解加入這些類中,這時(shí)我們的Inject就失效了。

那么就需要封裝第三方的類庫(kù),封裝的代碼怎么管理呢,總不能讓這些封裝的代碼散落在項(xiàng)目中的任何地方,總得有個(gè)好的管理機(jī)制,那Module就可以擔(dān)當(dāng)此任。可以把封裝第三方類庫(kù)的代碼放入Module中,像Demo2:

目標(biāo)類A

public class A {    String aa = "小花";
//注意這里沒有用inject標(biāo)注    public A() {    }}

Moudle類(類名命名木有要求)

@Modulepublic class AModule {    @Provides    A providesA(){        return new A();    }}

Component類(類名命名木有要求)

@Component(modules = {AModule.class})public interface AComponent {    void inject(NewActivity act);}

頁面NewActivity

public class NewActivity extends AppCompatActivity {    @Inject    A a1;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_new);        //實(shí)例化component對(duì)象        AComponent component = DaggerAComponent.builder().aModule(new AModule()).build();        //注入        component.inject(this);        Log.e("---------",a1.aa);    }}

打印結(jié)果:小花

其中,Module類其實(shí)是簡(jiǎn)單工廠模式,類里面基本都是創(chuàng)建類實(shí)例的方法

這時(shí)Component是怎樣的工作原理:

Component是注入器,它一端連接目標(biāo)類,另一端連接目標(biāo)類依賴實(shí)例,它把目標(biāo)類依賴實(shí)例注入到目標(biāo)類中。上文中的Module是一個(gè)提供類實(shí)例的類,所以Module應(yīng)該是屬于Component的實(shí)例端的(連接各種目標(biāo)類依賴實(shí)例的端),Component的新職責(zé)就是管理好Module,Component中的modules屬性可以把Module加入Component,modules可以加入多個(gè)Module。

Module中的創(chuàng)建類實(shí)例方法用Provides進(jìn)行標(biāo)注,Component在搜索到目標(biāo)類中用Inject注解標(biāo)注的屬性后,Component就會(huì)去Module中去查找用Provides標(biāo)注的對(duì)應(yīng)的創(chuàng)建類實(shí)例方法,這樣就可以解決第三方類庫(kù)用dagger2實(shí)現(xiàn)依賴注入了。

那么問題來了,如果實(shí)例D的構(gòu)造也用@Inject標(biāo)注的話,這時(shí)Component應(yīng)該怎么作為橋梁的呢?

首先Component會(huì)搜索目標(biāo)類中用Inject標(biāo)注的屬性(B),然后如果有Module類,就會(huì)先從Module類中找,看有沒有用@Provides標(biāo)注的方法,是否提供了這個(gè)實(shí)例,有則創(chuàng)建返回;沒有的話,就去看這個(gè)實(shí)例(B)的構(gòu)造方法是否Inject標(biāo)注,有則,創(chuàng)建返回;也就是說,Component會(huì)先去從Module中找,沒有的話,才去構(gòu)造中找

注意:Component可以包含一個(gè)或多個(gè)Module類,也可以不包含,Demo1即使不包含

如果構(gòu)造是有參數(shù)的,Component應(yīng)該怎么連接?

public class D {    String name = "卡卡卡";    public D(B b) {    }}

以下是初始化目標(biāo)類的具體步驟

步驟1:查找Module中是否存在創(chuàng)建該類的方法。步驟2:若存在創(chuàng)建類方法,查看該方法是否存在參數(shù) 步驟2.1:若存在參數(shù),則按從**步驟1**開始依次初始化每個(gè)參數(shù) 步驟2.2:若不存在參數(shù),則直接初始化該類實(shí)例,一次依賴注入到此結(jié)束步驟3:若不存在創(chuàng)建類方法,則查找Inject注解的構(gòu)造函數(shù), 看構(gòu)造函數(shù)是否存在參數(shù) 步驟3.1:若存在參數(shù),則從**步驟1**開始依次初始化每個(gè)參數(shù) 步驟3.2:若不存在參數(shù),則直接初始化該類實(shí)例,一次依賴注入到此結(jié)束

注意:如果參數(shù)沒有從module中找到,其構(gòu)造又未被inject標(biāo)注,則會(huì)報(bào)錯(cuò)

所以:在module中,不要出現(xiàn)參數(shù)和返回值一樣,如上所述的話,會(huì)造成死循環(huán)

總結(jié):

Inject,Component,Module,Provides是dagger2中的最基礎(chǔ)最核心的知識(shí)點(diǎn)。奠定了dagger2的整個(gè)依賴注入框架。

Inject主要是用來標(biāo)注目標(biāo)類的依賴和依賴的構(gòu)造函數(shù)Component它是一個(gè)橋梁,一端是目標(biāo)類,另一端是目標(biāo)類所依賴類的實(shí)例,它也是注入器(Injector)負(fù)責(zé)把目標(biāo)類所依賴類的實(shí)例注入到目標(biāo)類中,同時(shí)它也管理Module。Module和Provides是為解決第三方類庫(kù)而生的,Module是一個(gè)簡(jiǎn)單工廠模式,Module可以包含創(chuàng)建類實(shí)例的方法,這些方法用Provides來標(biāo)注
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 万安县| 绥滨县| 隆尧县| 元江| 鸡泽县| 青州市| 涿鹿县| 平湖市| 中江县| 承德市| 罗江县| 大关县| 桃园市| 巴彦县| 安徽省| 河津市| 察哈| 堆龙德庆县| 高雄市| 观塘区| 青岛市| 华亭县| 祁门县| 明水县| 淮阳县| 溧水县| 青铜峡市| 洛阳市| 囊谦县| 山东| 石棉县| 合阳县| 汕尾市| 资溪县| 卓资县| 荣成市| 满城县| 郴州市| 会宁县| 长兴县| 政和县|