Dagger2基本使用

Dagger是一个完全静态的、编译时的依赖注入框架,适用于java、Kotlin语言,主要用在Android开发中。早期要Square创建,现在由Google进行维护。
Dagger相比较其它依赖注入框架最大优势是没有采用反射技术,使用APT技术。

引入Dagger

在Moudle的build中引入

    implementation 'com.google.dagger:dagger-android:2.41'
    implementation 'com.google.dagger:dagger-android-support:2.41' // if you use the support libraries
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.41'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.41'

注解的初步使用

四个基础的注解:

  • @Inject 主要有两个作用,一个是使用构造函数上,通过标记构造函数唐Dagger2来使用(Dagger2通过这个标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖,另外一个作用就是标记在需要依赖的变量让Dagger2为其提供依赖。
    @Inject还能使用在方法上,用来set变量
  • @Component 一般用于标注接口,被标注了Component的接口在编译时会产生相应的类的实例来作为提供依赖方和需要依赖方之间的桥梁,把相关依赖注入其中。Component标注的接口在编译时会生成该接口的实现类(例如MainActivityComponent标注的接口会生成接口类DaggerMainActivityComponent)。

第一种使用方法:
1.生成@Inject标注的构造方法
2.生成@Component标注的中间接口
3.@Inject标注变量
4。通过DaggerxxxComponent实现注入

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

    public String show(){
        return getClass().getSimpleName();
    }
}

接下来需要创建一个用@Component标注的接口,这个接口是一个注入器,用来将对象实例注入到调用方。

@Component
public interface MainComponent {
    void inject(MainActivity mainActivity);
}

完成后可能需要reBuild项目生成DaggerMainComponent类。

public class MainActivity extends AppCompatActivity {
    //定义需要被注入的实例
    @Inject
    Car mCar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实现注入
        DaggerMainComponent.create().inject(this);
        Toast.makeText(this,"this is " + mCar.show(),Toast.LENGTH_LONG).show();
    }
}

带参构造方法或者第三方对象注入

在开发中经常使用到第三方或者有参数的构造方法,这时候我们应该如何进行标注?这时候需要使用@Module和@Provide

  • @Provide用来标注一个方法,该方法可以需要提供依赖时被调用,从而把预先提供好的对象当做依赖标注了@Injection的变量赋值。Provide主要用于标注Module里的方法。
    1.创建两个类
public class Gear {
    public Gear() {
    }

    @NonNull
    @Override
    public String toString() {
        return this.getClass().getSimpleName();
    }
}

public class Engine {
    public Engine(Gear gear) {
        gear.toString();
    }
}

Engine构造方法中有使用Gear的对象
创建Module类

@Module
public class MainActivityModule {
    @Provides
    public Engine provideEngine(){
        return new Engine(new Gear());
    }
}

这里使用了@Module标注了类用@Provides标注方法

@Component(modules = {MainActivityModule.class})
public interface MainComponent {
    void inject(MainActivity mainActivity);
}

modules类

//modules 中可以有多个Module类,通过","隔开
@Component(modules = {MainActivityModule.class})
public interface MainComponent {
    void inject(MainActivity mainActivity);
}

实现注入

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    //定义需要被注入的实例
    @Inject
    Car mCar;
    @Inject
    Engine mEngine;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实现注入
        DaggerMainComponent.create().inject(this);
        //Toast.makeText(this,"this is " + mCar.show(),Toast.LENGTH_LONG).show();
        Toast.makeText(this,"this is " + mEngine.toString(),Toast.LENGTH_LONG).show();
        Log.d(TAG, "onCreate: " + mCar.show() + " Engine " + mEngine.toString());
    }
}

限定符

在面向接口编程中,经常需要使用一个接口,多个实现类的方式进行操作,那么应该如何进行这种类型的初始化?这里需要使用到@Qualifier或者@name注解,同时这也是当对象有多个构造函数时的解决方法。

  • @Qualifier限定符,可以用来给注解做注解
  • @Named是被@Qualifier注解的,可以省略手动创建注解类,主要用来注解方法和对象
    操作需要两步:
    1.创建@Qualifier注解过的注解
    2.给Provider方法加上@Qualifier注解
    示例:
    创建一个接口
public interface Mechanical {
}

创建注解

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

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

修改Car和Engine

public class Car implements Mechanical{
    @Inject
    public Car() {
    }

    @NonNull
    @Override
    public String toString() {
        return getClass().getSimpleName();
    }
}

public class Engine implements Mechanical{
    @Inject
    public Engine(Gear gear) {
        gear.toString();
    }
}

修改Module类

@Module
public class MainActivityModule {
    @QualifierEngine
    @Provides
    public Mechanical provideEngine(){
        return new Engine(new Gear());
    }

    @QualifierCar
    @Provides
    public Mechanical provideCar(){
        return new Car();
    }
}

//modules 中可以有多个Module类,通过","隔开
@Component(modules = {MainActivityModule.class})
public interface MainComponent {
    void inject(MainActivity mainActivity);
}

使用

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    //定义需要被注入的实例
    @QualifierCar
    @Inject
    Mechanical mCar;
    @QualifierEngine
    @Inject
    Mechanical mEngine;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实现注入
        DaggerMainComponent.create().inject(this);
        //Toast.makeText(this,"this is " + mCar.show(),Toast.LENGTH_LONG).show();
        Toast.makeText(this,"this is " + mEngine.toString(),Toast.LENGTH_LONG).show();
        Log.d(TAG, "onCreate: " + mCar.toString() + " Engine " + mEngine.toString());
    }
}

@Named的使用方法为:
1.使用@Named标记Module中生成类实例的方法
2.使用@Named标注目标类中相应类实例

@Module
public class MainActivityModule {
    @Named("Engine")
    @Provides
    public Mechanical provideEngine(){
        return new Engine(new Gear());
    }

    @Named("Car")
    @Provides
    public Mechanical provideCar(){
        return new Car();
    }
}

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    //定义需要被注入的实例
    @Named("Car")
    @Inject
    Mechanical mCar;
    @Named("Engine")
    @Inject
    Mechanical mEngine;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实现注入
        DaggerMainComponent.create().inject(this);
        //Toast.makeText(this,"this is " + mCar.show(),Toast.LENGTH_LONG).show();
        Toast.makeText(this,"this is " + mEngine.toString(),Toast.LENGTH_LONG).show();
        Log.d(TAG, "onCreate: " + mCar.toString() + " Engine " + mEngine.toString());
    }
}

@Named相当于把@Qualifier封装了一下,操作起来更简单

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值