• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 安卓開發學習之Dagger2的使用

    標簽: 安卓開發  Dagger2

    今天閑來無事,就總結一下前些日子對Dagger2的學習使用


    介紹

    Dagger2是一個利用注解來構造類的實例的東西,網上稱此為依賴注入。


    Dagger2主要有這么幾個注解@Inject、@Module、@Provides、@Component、@Qualifier和@Scope。在這篇文章中,我會為大家一一演示它們的簡單用法,供大家入門。


    場景構造

    我們先構造一個場景:咖啡店造咖啡

        定義接口CoffeeMaker,咖啡廚子Cooker(真正做咖啡的),接口實現類SimpleMaker(里面的Cooker屬性負責做咖啡),咖啡機CoffeeMachine(里面的CoffeeMaker屬性負責生產咖啡)

        如果按普通的寫,我們就會這么實例化一個咖啡機:

    CoffeeMachine machine = new CoffeeMachine(new SimpleMaker(new Cooker("李四","信陽毛尖")));

        一下用了三個new,而用Dagger2,我們不用(不用每次)new,也能實例化咖啡機對象


    添加依賴

    annotationProcessor 'com.google.dagger:dagger-compiler:2.0.1'
    compile 'com.google.dagger:dagger:2.0'
    compile 'org.glassfish:javax.annotation:10.0-b28'

    @Inject

        我們最終要實例化咖啡機,所以就給咖啡機的構造方法用上@Inject

    public class CoffeeMachine {
        private SimpleMaker simpleMaker;
    
        @Inject
        public CoffeeMachine(CoffeeMaker maker) {
            this.simpleMaker = (SimpleMaker) maker;
        }
    
        public void makeCoffee(){
            simpleMaker.makeCoffee();
        }
    }

        注意,每個類頂多只能有一個構造方法使用@Inject注解


    @Provides和@Module

    而后我們再用@Provides提供對象,而@Provides必須在@Module類中使用

    @Module
    public class SimpleModule {
        private String name;
        private String kind;
    
        public SimpleModule(String name, String kind) {
            this.name = name;
            this.kind = kind;
        }
    
        public SimpleModule() {}
    
        @Provides
        Cooker provideCooker() {
            return new Cooker(name, kind);
        }
    
        @Provides
        CoffeeMaker provideCoffeeMaker(Cooker cooker) {
            return new SimpleMaker(cooker);
        }
    }

        注意幾點:1、使用@Provides的方法,名字必須以provide開頭

                       2、參數列表里的參數,也必須有相應的@Provides方法。

        正因為第二點,@Module類可能不是那么靈活,不能隨時改變name和kind,因為我們不能給String也來個@Provides。

        如果要用的話,最合理的是這樣用:

    @Provides
    String provideName(String name){
        return name;
    }

        但是編譯的時候就GG了:


       編譯器說有倆解決方案:使用@Provides提供String和給String的構造方法使用@Inject。都是死路,所以String這樣的類不能用@Provides來提供,那么我能想到的就是用屬性了,就是我步驟3的代碼


    @Component

    搭橋,使用@Component。這里是構造一個接口,編譯后會生成相應的類,類名是Dagger+自定義Module類名

    @Component(modules = SimpleModule.class)
    public interface SimpleComponent {
        void inject(MainActivity activity);
    }

     

    正式使用

    現在,我們就可以在UI中使用我們的Dagger2了(但記住,要先編譯,再使用下面的DaggerSimpleComponent

    public class MainActivity extends AppCompatActivity {
        private SimpleComponent simpleComponent;
        @Inject
        CoffeeMachine coffeeMachine;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            simpleComponent = DaggerSimpleComponent.builder().simpleModule(new SimpleModule("我","洞庭碧螺春"))
                    .build();
            simpleComponent.inject(this);
            coffeeMachine.makeCoffee();
        }
    }

        可以看到,我們在實例化咖啡機時,沒有到new,只是在聲明的時候,加了一個@Inject注解,就像ButterKnife一樣。


        至此,我們用了@Inject、@Module、@Provides和@Component四個注解,思路亦是很清晰:

            @Inject用來標記最終注入的類對象和類的構造方法

            @Module提供最終類的構造方法所需各組件的provide方法,每一個provide方法都要用@Provide注解標記

            @Component負責把@Module類注入到UI和最終類對象中,實例化最終類對象的同時,實現最終類對象與UI生命周期的綁定。


        而后,我們在說說最后倆注解@Qualifier和@Scope。前者是標識符,后者表示作用范圍(作用范圍內單例,亦稱局部單例)


    @Qualifier

        先說@Qualifier

        方才我們說了,provides方法要有返回類型,不能為空,而且provides方法不是以方法名和參數區分的。但如果有需求導致兩個provides方法返回值類型一樣,該當如何?那就用到@Qualifier了,@Qualifier和返回類型,是provides方法區分彼此的標志。

        使用步驟:

            1、定義倆注解@A和@B,用上@Qualifier,表示這是倆標識符,同時用上@Retention(RetentionPolicy.RUNTIME),表示注解運行時有效

    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    public @interface A {}    
    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    public @interface B {
    }

            2、然后,我們再定義一個父子咖啡師

    public class FatherAndSonCoffeeMaker implements CoffeeMaker{
        private Cooker father,son;
    
        public FatherAndSonCoffeeMaker(@A Cooker father,@B Cooker son) {
            this.father = father;
            this.son = son;
        }
    
    
        @Override
        public void makeCoffee() {
            father.makeCoffee();
            son.makeCoffee();
        }
    }

            構造方法里的@A和@B表示兩個參數不一樣,要用不同的provides方法提供,這些provides方法我們稍后再說

        

           3、然后對SimpleMaker的構造方法的參數也要指明用Cooker的哪個provides方法

    public class SimpleMaker implements CoffeeMaker {
        Cooker cooker;
    
        public SimpleMaker(@A Cooker cooker) {
            this.cooker = cooker;
        }
    
        @Override
        public void makeCoffee() {
            cooker.makeCoffee();
        }
    }

           4、之后對咖啡機進行升級

    public class CoffeeMachine {
        private SimpleMaker simpleMaker;
        private FatherAndSonCoffeeMaker fatherAndSonCoffeeMaker;
    
        @Inject
        public CoffeeMachine(@A CoffeeMaker maker, @B CoffeeMaker maker2) {
            this.simpleMaker = (SimpleMaker) maker;
            this.fatherAndSonCoffeeMaker = (FatherAndSonCoffeeMaker) maker2;
        }
    
        public void makeCoffee1(){
            simpleMaker.makeCoffee();
        }
    
        public void makeCoffee2(){
            fatherAndSonCoffeeMaker.makeCoffee();
        }
    }

            同樣,兩個CoffeeMaker也用不同的provides方法提供


           5、而后我們就可以更改Module類了

    @Module
    public class SimpleModule {
        private String name;
        private String kind;
    
        public SimpleModule(String name, String kind) {
            this.name = name;
            this.kind = kind;
        }
    
        public SimpleModule() {}
    
        @Provides
        @A
        Cooker provideCooker() {
            return new Cooker(name, kind);
        }
    
        @Provides
        @B
        Cooker provideAnotherCooker() {
            return new Cooker(name + "`s son", kind);
        }
    
        @Provides
        @A
        CoffeeMaker provideCoffeeMaker(@A Cooker cooker) {
            return new SimpleMaker(cooker);
        }
    
        @Provides
        @B
        CoffeeMaker provideFDSCoffeeMaker(@A Cooker father, @B Cooker son) {
            return new FatherAndSonCoffeeMaker(father, son);
        }
    
    }

            可以看到,標記@A的Cooker的provides方法,提供的是爹,標記@B的Cooker的provides方法,提供的是兒;

                           標記@A的CoffeeMaker的provides方法,提供的是簡單maker,標記@B的CoffeeMaker的provides方法,提供的是父子maker


            6、最后,我們在主活動里使用父子咖啡maker,卻發現基本不用怎么改動(都在@Module和那些類里面改完了)

    public class MainActivity extends AppCompatActivity {
        private SimpleComponent simpleComponent;
        private AppComponent appComponent;
        @Inject
        CoffeeMachine coffeeMachine;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            simpleComponent = DaggerSimpleComponent.builder().simpleModule(new SimpleModule("我","洞庭碧螺春"))
                    .build();
            simpleComponent.inject(this);
            coffeeMachine.makeCoffee1();
            Log.i("Cooker","-------------------------------------");
            coffeeMachine.makeCoffee2();
            Log.i("Cooker","-------------------------------------");
    
        }
    }


    @Scope

        最后,我們再說一下@Scope,它是用來提供局部單例的。

        使用步驟:

            1、創建注解,名字隨便,用上@Scope,表示被這個注解是用來表示局部單例的。同時使之運行時有效

    @Scope
    @Retention(RetentionPolicy.RUNTIME)
    public @interface perActivity {}

            2、然后,在我們的module類中,給父子咖啡maker的provides方法,用上局部單例注解

    @Provides
    @B
    @perActivity
    CoffeeMaker provideFDSCoffeeMaker(@A Cooker father, @B Cooker son) {
        return new FatherAndSonCoffeeMaker(father, son);
    }

            3、之后,給Component也用上局部單例

    @perActivity
    @Component(modules = SimpleModule.class)
    public interface SimpleComponent {
        void inject(MainActivity activity);
    }

                這樣,我們調用inject()方法后,Component、父子咖啡maker的provides方法,都會在MainActivity中保持單例。

                如果我們再加一個注入到BActivity,那倆就會在MainActivity和BActivity這倆活動中保持單例,在其他活動中,就不會保持單例。

                是所謂“局部單例”。

        

            4、主活動中測試一下(給咖啡機里父子maker加上get方法)

    public class MainActivity extends AppCompatActivity {
        private SimpleComponent simpleComponent;
        private AppComponent appComponent;
        @Inject
        CoffeeMachine coffeeMachine;
    
        @Inject
        CoffeeMachine coffeeMachine2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            simpleComponent = DaggerSimpleComponent.builder().simpleModule(new SimpleModule("我","洞庭碧螺春"))
                    .build();
            simpleComponent.inject(this);
            coffeeMachine.makeCoffee1();
            Log.i("Cooker","-------------------------------------");
            coffeeMachine.makeCoffee2();
            Log.i("Cooker","-------------------------------------");
            Log.i("Cooker","Two fdsCoffeeMachine are same? --> "+(coffeeMachine.getFatherAndSonCoffeeMaker() == coffeeMachine2.getFatherAndSonCoffeeMaker()));
        }
    }

                會發現,最后的結果是true。
    版權聲明:本文為qq_37475168原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_37475168/article/details/79793962

    智能推薦

    Dagger2使用詳解

    Dagger2使用詳解 什么是依賴注入? 依賴注入就是將調用者依賴的對象實例通過一定的方式從外部傳入,解決了各個類之間的耦合問題。 這個外部,正是dagger2容器。需要什么對象從容器中取就行了,調用和被調用方被隔離開,通過一個容器將他們聯系起來,從而實現了解耦。 Dagger2是Google出的依賴注入框架。Dagger2的原理是在編譯期生成相應的依賴注入代碼。其他框架是在運行時期反射獲取注解內...

    Dagger2 使用(一)

    2019獨角獸企業重金招聘Python工程師標準>>> 前言     dagger2主要的作用是注入,在dagger中,所謂注入其實就是給對象賦值,遵循JSR-330標準     dagger2 主要分成以下幾個部分     被注入對象 injection 比如需要被注入 mChain 和 mWheel 注入的提供者(m...

    Android開發之dagger2簡單理解

    理解簡述 Android開發技術層出不窮。站在別人肩膀上看風景,的確省了不少事。前一段時間為了鍛煉下自己的能力,就從鴻洋大神微信公眾號的推送里面,下了個完整的項目,想試著自己跟著寫一下,也算是追隨下主流的腳步吧,這里給下下載的鏈接點擊打開鏈接,作品的簡介:微閱是一款使用 MVP + Retrofit2 + Rxjava + dagger2 等框架開發的閱讀軟件。包括新聞、視頻、煎蛋三個模塊,項目的...

    Android之Dagger2使用,全面講解各種可能遇到的報錯

    Dagger2 先給大家講講博主的辛酸歷程,第一次使用時我的AS版本是3.6.2當時使用dagger就一直出不來下面這條語句(記好了,寫完一定要編譯一下) 然后老師說是版本問題,然后就降了版本,當時沒什么問題,后來使用過SVN,然后至關重要的一點,我當時在這里配置了代碼忽略(現在是取消配置的) 這一步就會讓app目錄下的build文件消失 消失之后,你無論怎么編譯也不會出來,在取消忽略后終于重見天...

    mvp架構,dagger2,butterknife的使用

    mvp架構,dagger2,butterknife的使用 butterKnife框架簡介 ButterKnife的優勢 ButterKnife的使用 dagger2 Dagger2是什么? 框架說明 Dagger2與butterknife區別 依賴注入 Dagger2注解說明 Dagger2基本使用: Dagger2復雜使用: 小結 MVP 步驟 Androidx版本MVP Android中的MV...

    猜你喜歡

    Dagger2的簡單使用及解析

    Dagger2是什么 Dagger2是一款基于Java注解來實現的完全在編譯階段完成依賴注入的開源庫,主要用于模塊間解耦、提高代碼的健壯性和可維護性。Dagger2在編譯階段通過apt利用Java注解自動生成Java代碼,然后結合手寫的代碼來自動幫我們完成依賴注入的工作。 不用Dagger2的代碼 有個Student類, 我需要在多個Activity中都創建這個類的對象。需要這么寫: 如果我的St...

    【Android】Dagger2在MVVM中的使用

    背景 一個標準的Android的MVVM架構是分層規劃實現的,各層之間有清晰的依賴關系。借助Dagger2完成MVVM各層所需的依賴注入,可以讓項目結構變得更清爽和更可維護。 雖然Dagger2有一定使用門檻,但是MVVM的項目結構大都相同,實現一個Dagger2+Retrofit2(+OkHttp3)+ViewModel 的最小構成實踐,對其他類似項目具有一定參考意義。 構成 1. gradle...

    Dagger2的基礎使用與原理

    Dagger2的基礎使用與原理 Dagger2的基礎使用與原理 前言 基礎使用 實現原理 Dagger2的基礎使用與原理 前言 Dagger 2 是基于 Java Specification Request(JSR) 330標準。利用 JSR 注解在編譯時生成代碼,來注入實例完成依賴注入。 什么是依賴注入? 是面向對象編程中的一種設計原則,可以用來減低計算機代碼之間的耦合度。通過控制反轉,對象在被...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    精品国产乱码久久久久久蜜桃不卡