Dagger2學習入門

目錄

前置:

三種常用的依賴注入方式:

構造器注入:

setter方法注入:

接口注入:

Dagger簡單注入:

1.依賴創建:構造方法提供依賴

1.依賴創建:Module類提供依賴

2.依賴注入位置:屬性注入 User注入

2.依賴注入位置:方法注入 User2注入

3.讓dagger知道從哪兒獲取依賴,注入依賴到哪兒:構造方法提供依賴

3.讓dagger知道從哪兒獲取依賴,注入依賴到哪兒:Module類提供依賴

4.生成的代碼

關鍵字

@Inject

@Componet 單獨依賴(modules)

@Module、@Provides

@Named

@Qualifier

@Componet 嵌套依賴(dependencies)

@Subcomponet 嵌套依賴

@Singleton

@Scope

MapKey和Lazy用到了再補充。。。。。


dagger2 github

官方文檔


前置:

依賴倒置原則、控制反轉(Inversion of Control)、依賴注入(Dependency Injection) 有一定的瞭解。

依賴倒置:高層不依賴低層而依賴抽象,抽象不依賴實現類。換言之,解耦具體實現,提升擴展性。

控制反轉:降低類與類耦合度。包括:依賴注入和依賴查找兩種實現方式。

依賴注入:不直接在需要依賴的地方new創建依賴,將依賴部分與邏輯分離、解耦。

 

幾個明顯的坑:

  • Component inject(container c) 容器必須傳入與你實際調用inject相同的類。也就是說不能c傳入BaseActivity,實際調用在XActivity。
  • 一個容器不能注入多個相同依賴,或者用@qualifier註明不同Provides。
  • 很多註解都需要配對使用,否則報錯,特別注意。

 

三種常用的依賴注入方式:

A依賴B。其實三種方式平時也在用,只是沒有特別去關注。

構造器注入:

public class InjectionA {
    private B b;

    public InjectionA(B b) {
        this.b = b;
    }
}

 

setter方法注入:

public class InjectionA {
    private B b;

    public void setB(B b) {
        this.b = b;
    }
}

 

接口注入:

interface Inject{
    void inject(B b);
}

public class InjectionA implements Inject{
    private B b;

    @Override
    public void inject(B b) {
        this.b = b;
    }
}

 

Dagger簡單注入:


1.依賴創建:構造方法提供依賴

package com.fengzhen.dagger;

import javax.inject.Inject;

public class User {

    String name;

    // 提供依賴
    @Inject
    public User() {
        this.name = "張三";
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

1.依賴創建:Module類提供依賴

package com.fengzhen.dagger;

public class User2 {
    String name;

    public User2(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.fengzhen.dagger;

import dagger.Module;
import dagger.Provides;

@Module
public class ActivityModule {

    @Provides
    User2 provider(){
        return new User2("李四");
    }
}

 

2.依賴注入位置:屬性注入 User注入

package com.fengzhen.dagger;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {

    private TextView mTV;
    private Button mBtn;

    // 哪裏需要依賴?
    @Inject
    User mUser;

    @Inject
    User2 mUser2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTV = (TextView) findViewById(R.id.tv);
        mBtn = (Button) findViewById(R.id.btn);
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mTV.setText(/*mUser.getName() + */mUser2.getName());
            }
        });

        DaggerActivityComponet.create().inject(this);
    }
}

 

2.依賴注入位置:方法注入 User2注入

不常用,一般用於需要this初始化的情況。

package com.fengzhen.dagger;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import javax.inject.Inject;

public class MainActivity extends AppCompatActivity {

    private TextView mTV;
    private Button mBtn;

    // 哪裏需要依賴?
    @Inject
    User mUser;

    User2 mUser2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.i("fengzhen", "onCreate: ==onCreate方法被調用");

        setContentView(R.layout.activity_main);

        mTV = (TextView) findViewById(R.id.tv);
        mBtn = (Button) findViewById(R.id.btn);
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mTV.setText(mUser.getName() + mUser2.getName());
            }
        });

        DaggerActivityComponet.create().inject(this);
    }

    @Inject
    public void setmUser2(User2 mUser2) {
        Log.i("fengzhen", "setmUser2: ==set方法被調用");
        this.mUser2 = mUser2;
    }
}

 

3.讓dagger知道從哪兒獲取依賴,注入依賴到哪兒:構造方法提供依賴

package com.fengzhen.dagger;

import dagger.Component;

// 如何將依賴注入給對象
@Component()
public interface ActivityComponet {
    void inject(MainActivity mainActivity);
}

 

3.讓dagger知道從哪兒獲取依賴,注入依賴到哪兒:Module類提供依賴

這裏@Componet傳入了提供依賴的Class

package com.fengzhen.dagger;

import dagger.Component;

// 如何將依賴注入給對象
@Component(modules = ActivityModule.class)
public interface ActivityComponet {
    void inject(MainActivity mainActivity);
}

4.生成的代碼

生成路徑:dagger2demo/build/generated/source/apt/debug/

User_Factory: 構造方法使用@Inject生成,靜態工廠創建依賴實例。

ActivityModule_ProviderFactory: 根據Module類靜態工廠創建依賴實例。

MainActivity_membersInjector: 拿到創建的依賴注入需要依賴的位置。

DaggerActivityComponet:實現ActivityComponet接口,實現具體的關聯邏輯。

 

關鍵字

@Inject

@Target({ METHOD, CONSTRUCTOR, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Inject {}

1.方法上

類似方法注入,構造器執行後調用此方法。

2.構造器上

提供依賴/注入依賴,視具體情況定。

3.屬性上

最常用的屬性注入。

 

@Componet 單獨依賴(modules)

@Retention(RUNTIME)
@Target(TYPE)
@Documented
public @interface Component {
  Class<?>[] modules() default {};
  Class<?>[] dependencies() default {};

  @Target(TYPE)
  @Documented
  @interface Builder {}
}

void inject()

指定注入目標,查找@Inject註解,注入對象。

modules

傳入Module方式的提供依賴類。

 

@Module、@Provides

@Module表明該類可以提供依賴,@Provides代表了具體提供不同依賴的方法。

 

@Named

提供相同依賴的不同實例,用來標記類別。

@Module
public class ActivityModule {

    @Provides
    @Named("user2")
    IUser provider(){
        return new User2("李四");
    }

    @Provides
    @Named("user1")
    IUser providerUser(){
        return new User("張三");
    }
}
    // 哪裏需要依賴?
    @Inject
    @Named("user1")
    IUser mUser;

    @Inject
    public void setmUser2(@Named("user2") IUser mUser2) {
        Log.i("fengzhen", "setmUser2: ==set方法被調用");
        this.mUser2 = mUser2;
    }

 

@Qualifier

功能類似於@named,用來自定義註解,實現區分的效果。

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

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface AUser2 {}
@Module
public class ActivityModule {

    @Provides
//    @Named("user2")
    @AUser2
    IUser provider(){
        return new User2("李四");
    }

    @Provides
//    @Named("user1")
    @AUser
    IUser providerUser(){
        return new User("張三");
    }
}
    // 哪裏需要依賴?
    @Inject
//    @Named("user1")
    @AUser
    IUser mUser;

    @Inject
    public void setmUser2(/*@Named("user2")*/@AUser2 IUser mUser2) {
        Log.i("fengzhen", "setmUser2: ==set方法被調用");
        this.mUser2 = mUser2;
    }

 

@Componet 嵌套依賴(dependencies)

已經瞭解了 module 的使用。dependencies可以將Componet相互嵌套起來使用。

將整個流程代碼貼一次。省略IUser、User、User2、AUser、AUser2。

Store

package com.fengzhen.dagger.subcomponent;

import com.fengzhen.dagger.IUser;

public class Store {
    
    IUser user;

    public Store(IUser user) {
        this.user = user;
    }

    public String getUserName() {
        return user.getName();
    }
}

IUser依賴提供:UserModule

package com.fengzhen.dagger;

import dagger.Module;
import dagger.Provides;

@Module
public class UserModule {

    @Provides
    @AUser2
    IUser provider() {
        return new User2("User2李四");
    }

    @Provides
    @AUser
    IUser providerUser() {
        return new User("User張三");
    }
}

IUser註解組件:IUserComponet

@Component(modules = UserModule.class)
public interface IUserComponet {

    @AUser
    IUser getUser();

    @AUser2
    IUser getUser2();
}

Store依賴提供:StoreModule

@Module
public class StoreModule {

    @Provides
    Store provideStore(@AUser2 IUser user){
        return new Store(user);
    }
}

Store註解組件:StoreComponet

這裏StoreComponet依賴於UserComponet,寫法如下:

@Component(modules = StoreModule.class,
        dependencies = IUserComponet.class)
public interface StoreComponent {
    Store getStore();
}

Container指定組件:ActivityComponet

如果Activity仍需要注入IUser,取消註釋即可。

// 如何將依賴注入給對象
@Component(/*modules = UserModule.class,*/
        dependencies = StoreComponent.class)
public interface ActivityComponet {
    void inject(MainActivity mainActivity);
}

Container注入

        DaggerActivityComponet.builder()
                .storeComponent(DaggerStoreComponent.builder()
                        .iUserComponet(DaggerIUserComponet.create())
                        .build())
                .build()
                .inject(this);

即。每個Bean、Module、Componet爲整體,缺一不可,可通過dependencies將組與組連接嵌套在一起。

 

@Subcomponet 嵌套依賴

@Componet 嵌套依賴的更加緊密的實現方式。只需要修改Componet實現

@Component(modules = UserModule.class)
public interface IUserComponet {
//
//    @AUser
//    IUser getUser();
//
//    @AUser2
//    IUser getUser2();

    StoreComponent plus(StoreModule storeModule);
}
//@Component(modules = StoreModule.class,
//        dependencies = IUserComponet.class)
@Subcomponent(modules = StoreModule.class)
public interface StoreComponent {
//    Store getStore();
    ActivityComponet plus();
}
// 如何將依賴注入給對象
//@Component(modules = UserModule.class,
//        dependencies = StoreComponent.class)
@Subcomponent
public interface ActivityComponet {
    void inject(MainActivity mainActivity);
}

Container注入

        DaggerIUserComponet.create()
                .plus(new StoreModule())
                .plus()
                .inject(this);

兩者區別:

  • dependencies能單獨使用,而Subcomponent必須由Component調用方法獲取
  • Container使用差別,dependencies使用creat(),Subcomponent使用new。
  • dependencies可將低層User也進行注入,Subcomponent聯繫緊密不能注入。

 

@Singleton

實現依賴單例。每次都提供同一個實例,實現與Componet同生命週期的單例。

且必須配對使用,Module和Componet必須配對使用否則報錯。

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
        DaggerActivityComponet.create().inject(this);

        StoreComponent component = DaggerStoreComponent.create();
        Store containerA = new Store();
        Store containerB = new Store();
        component.inject(containerA);
        component.inject(containerB);

        Log.i("fengzhen", "onCreate: " + mUser2.toString());
        Log.i("fengzhen", "onCreate: " + containerA.user.toString());
        Log.i("fengzhen", "onCreate: " + containerB.user.toString());

分別創建兩個Componet,分別注入Activity和兩個Store,打印結果可見:

兩個Store的User是一個實例,且與Activity的User不是一個實例。

 

@Scope

@Singleton是@Scope的一種,也是官方給出來的,我們也可以自定義Scope實現我們想要的生命週期。

定義一個App全局單例。

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface AppLifecycle {
}
package com.fengzhen.dagger;

import android.app.Application;

import com.fengzhen.dagger.scope.ConfigComponet;
import com.fengzhen.dagger.scope.DaggerConfigComponet;

public class App extends Application {

    private static ConfigComponet mConfigComponet;

    @Override
    public void onCreate() {
        super.onCreate();
        // 與App生命週期進行綁定,實現全App單例
        mConfigComponet = DaggerConfigComponet.create();
    }

    /**
     * 具體容器進行自定義注入
     */
    public static ConfigComponet getConfigComponet() {
        return mConfigComponet;
    }
}

 

MapKey和Lazy用到了再補充。。。。。

 

 

 

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