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 嵌套依赖

 

@Module + @Binds

@Singleton

@Scope

Map

Set


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联系紧密不能注入。

 

@Module + @Binds

@Binds和@Provides的功能类似,不同于:

@Provides 注解可以提供第三方类和接口的注入;

@Binds 注解只能提供接口的注入,且只能注解抽象方法。

 

Module:(这里重写了一遍嵌套的过程,所以类名不一样了)

@Module
public abstract class StoreModule {

//    @Provides
//    IStore provideStore(Customer customer){
//        return new Store(customer);
//    }

    // 传入参数为具体的返回接口(IStore)的实现类
    @Binds
    abstract IStore provideStore(Store store);
}

Store:依赖类,构造方法@Inject,通过Component依赖传入Customer。

public class Store implements IStore {
    Customer customer;

    @Inject
    public Store(Customer customer) {
        this.customer = customer;
    }

    public String getName(){
        return customer.name;
    }
}

剩下的就完全和前面的一模一样。

 

@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;
    }
}

 

Map

注入Map类型数据,目前支持int、string、long、class、自定义枚举。

Module:

    @Provides
    @IntoMap
    @IntKey(1)
    int provideUser111(){
        return 111;
    }

    @Provides
    @IntoMap
    @StringKey("user222")
    int provideUser222(){
        return 222;
    }

Container:

    @Inject
    Map<Integer, Integer> mSet;

    private void inject() {

        CollectComponet collectComponet = DaggerCollectComponet.create();
        collectComponet.inject(this);

        Log.i("fengzhenl", "inject: " + mSet.toString());
    }

 

Set

Module:

    @Provides
    @IntoSet
    @Singleton
    User2 provideUser2() {
        return new User2("multi张三");
    }

    @Provides
    @Singleton
    @ElementsIntoSet
    Set<User2> provideUser2Set() {
        return new HashSet<>(Arrays.asList(new User2("multi李四"), new User2("multi王五")));
    }

Container:

    @Inject
    Set<User2> mUserSet;

    private void inject() {

        CollectComponet collectComponet = DaggerCollectComponet.create();
        collectComponet.inject(this);

        Log.i("fengzhenl", "inject: " + mUserSet.toString());
    }

也可以通过此方式获取:

Component:

@Singleton
@Component(modules = UserMultiModule.class)
public interface CollectComponet {
    void inject(MainActivity activity);

    Set<User2> getUsers();
}

Container:

    @Inject
    Set<User2> mUserSet;

    private void inject() {

        CollectComponet collectComponet = DaggerCollectComponet.create();
        collectComponet.inject(this);

        Set<User2> users = collectComponet.getUsers();
        Log.i("fengzhenl", "inject: " + mUserSet.toString());
        Log.i("fengzhenl", "inject: " + users.toString());
   }

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值