Dagger2使用简介

概述

Dagger2 是一款使用在Java和Android上的依赖注入的一个类库。

使用

配置环境
在module的gradle文件中做如下配置

apply plugin: 'com.neenbedankt.android-apt'
apply plugin: 'me.tatarka.retrolambda'

compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }

 apt 'com.google.dagger:dagger-compiler:2.4'
    compile 'com.google.dagger:dagger:2.4'
    provided 'org.glassfish:javax.annotation:10.0-b28'

然后在最外层的gradle中配置

 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        classpath 'me.tatarka:gradle-retrolambda:3.2.4'

环境配置好了,我们来写代码

代码

用法一

先看一个简单的使用

public class Poetry {
    private String mPoem;
    @Inject  // 用Inject标记构造函数,表示用它来注入到目标对象中去
    public Poetry(){
        mPoem = "生活像海洋";
    }
    public Poetry(String content){
        mPoem = content;
    }
    public String getmPoem(){
        return mPoem;
    }
}

然后需要创建一个连接器,

@Component //用@Component表示这个接口是一个连接器,能用@Component注解的只
//能是interface或者抽象类
public interface MainActivityComponent {
    /**
     * 需要用到这个连接器的对象,就是这个对象里面有需要注入的属性
     * (被标记为@Inject的属性)
     * 这里inject表示注入的意思,这个方法名可以随意更改,但建议就
     * 用inject即可。
     */
    void inject(MainActivity activity);
}

最后我们在MainActivity中这样写

public class MainActivity extends AppCompatActivity {
    private TextView textView;
    @Inject //添加@Inject注解,表示这个mPoetry是需要注入的
    Poetry mpoery;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        // 使用Dagger2生成的类 生成组件进行构造,并注入
        DaggerMainActivityComponent.builder().build().inject(this);
        String str = mpoery.getmPoem();
        textView.setText( str);
    }
}

注意事项:
Inject标签注解的对象不能是private修饰的
Provides标签必须放在Module之中
在多个地方调用同一个连接器对同一个对象进行注解,会生成这个对象的多个实例,如果不想生成,可以使用@Scope标签。
@Scope的作用:标记当前生成实例的使用范围,标识一个类型的注射器只实例化一次,可以实现单例的效果

用法二

这里写图片描述

@Component(modules = ActivityModule.class)
public interface MainActivityComponent {
    void inject(MainActivity mainActivity);
}
public class UserModel {
    public String name;
    public int age;
    //只能够使用一个Inject
    public UserModel(String name,int age){
        this.name = name;
        this.age  = age;
    }
    @Inject
    public UserModel(){

    }
}
@Module
public class ActivityModule {
    @Provides
    public UserModel provideUserModel(){
        return new UserModel("小明",22);
    }
}
public class MainActivity extends AppCompatActivity {
    @Inject
    UserModel userModel;
    private MainActivityComponent mainActivityComponent;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
        //使用Module方式
//        mainActivityComponent = DaggerMainActivityComponent.builder().activityModule(new ActivityModule()).build();
//        mainActivityComponent.inject(this);
        //不使用module
        DaggerMainActivityComponent.builder().build().inject(this);
        textView.setText(userModel.toString());
    }
}

用法三

public class DemoApplication extends Application {
    @Inject
     LocationManager locationManager;//不能使用private修饰
     ApplicationComponent applicationComponent;
    private DemoApplication application;
    @Override
    public void onCreate() {
        super.onCreate();
        applicationComponent = DaggerApplicationComponent.builder().androidModule(new AndroidModule(this)).build();
        applicationComponent.inject(this);
        application = this;
    }
    public ApplicationComponent component(){
        return applicationComponent;
    }
}
@Component(modules = AndroidModule.class)
public interface ApplicationComponent {
    void inject(DemoApplication application);
}
@Module
public class AndroidModule {
    public DemoApplication application;

    public AndroidModule(DemoApplication application){
        this.application = application;
    }
    @Provides//提供context对象
    Context provideApplicationContext(){
        return application;
    }
    @Provides//提供locationmanager
    public LocationManager getLocationManager(){
        return (LocationManager) application.getSystemService(Context.LOCATION_SERVICE);
    }
}

用法四(带有参数的构造方法)

public class UserModel {
    public String name;
    public int age;
    private Context mContext;
    //只能够使用一个Inject
    public UserModel(String name,int age){
        this.name = name;
        this.age  = age;
    }
    @Inject
    //参数必须在module中标记出来
    public UserModel(Context context){
        mContext = context;
    }
}
@Module
public class AndroidModule {
    public DemoApplication application;

    public AndroidModule(DemoApplication application){
        this.application = application;
    }
    @Provides//提供context对象,作为UserModel的构造函数的参数
    Context provideApplicationContext(){
        return application;
    }
    @Provides//提供locationmanager
    public LocationManager getLocationManager(){
        return (LocationManager) application.getSystemService(Context.LOCATION_SERVICE);
    }
}
public class MainActivity extends AppCompatActivity {
    @Inject
    UserModel userModel;
    private MainActivityComponent mainActivityComponent;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView  = (TextView) findViewById(R.id.textview);
        MainActivityComponent activityComponent = DaggerMainActivityComponent.builder().androidModule
                (new AndroidModule((DemoApplication) getApplication())).build();
        activityComponent.inject(this);
        textView.setText(userModel.toString());
    }

用法五(单例)

要实现单例我们用@Singleton注解,这里有两个地方需要注意:
1.首先给我们的实体加上此注解

@Singleton
public class UserModel {
    public String name;
    public int age;
    private Context mContext;
    //只能够使用一个Inject
    public UserModel(String name,int age){
        this.name = name;
        this.age  = age;
    }
    @Inject
    //参数必须在module中标记出来
    public UserModel(Context context){
        mContext = context;
    }
}

2.给容器也加上此注解

@Singleton
@Component(modules = AndroidModule.class)
public interface MainActivityComponent {
    void inject(MainActivity mainActivity);
}

只有实现了上面两部,才能实现单例

public class MainActivity extends AppCompatActivity {
    @Inject
    UserModel userModel;
    @Inject
    UserModel userModel2;
    private MainActivityComponent mainActivityComponent;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView  = (TextView) findViewById(R.id.textview);
        mainActivityComponent = DaggerMainActivityComponent.builder().androidModule(new AndroidModule((DemoApplication) getApplication())).build();
        mainActivityComponent.inject(this);
        textView.setText(userModel.toString()+"\n"+userModel2.toString());
    }
}

此时我们的两个对象的地址就是同一个了。
如果不给实体加@Singleton注解,无法实现单例,如果只给实体加注解而不给容器加注解,运行时会出现如下的错误

这里写图片描述

用法六(单例)

我们用另一种方式实现单例,这种方式不需要在实体上注解,我们放到Module中

@Module
public class AndroidModule {
    public DemoApplication application;

    public AndroidModule(DemoApplication application){
        this.application = application;
    }
    @Provides//提供context对象,作为UserModel的构造函数的参数
    Context provideApplicationContext(){
        return application;
    }
    @Provides//提供locationmanager
    public LocationManager getLocationManager(){
        return (LocationManager) application.getSystemService(Context.LOCATION_SERVICE);
    }
    @Singleton
    @Provides
    public UserModel provideUserModel(){
        return new UserModel(application);
    }
}

MainActivityComponent 同样需要注解

@Singleton
@Component(modules = AndroidModule.class)
public interface MainActivityComponent {
    void inject(MainActivity mainActivity);
}

用法七(依赖其他组件)

@Module
public class AndroidModule {
    public DemoApplication application;
    private LocationManager locationManager;
    public AndroidModule(DemoApplication application){
        this.application = application;
        locationManager = (LocationManager) application.getSystemService(Context.LOCATION_SERVICE);;
    }

    @Singleton
    @Provides//提供context对象,作为UserModel的构造函数的参数
    Context provideApplicationContext(){
        return application;
    }

    @Singleton
    @Provides//提供locationmanager
    public LocationManager getLocationManager(){
        return locationManager;
    }

}
@Singleton
@Component(modules = AndroidModule.class)
public interface ApplicationComponent {
//注入到DemoApplication中
    void inject(DemoApplication application);
    LocationManager getLocationManager();//子组件需要Application中的某个实例的时候,需要提供这个接口
}
@PerActivity//如果对应的modules里面有@Scope注解,那么容器里也必须加上,此处为@PerActivity
//依赖ApplicationComponent
@Component(dependencies = ApplicationComponent.class,modules = ActivityModule.class)
public interface MainActivityComponent {
    void inject(MainActivity mainActivity);
}

这里我们自定义了一个注解@PerActivity

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}
@Module
public class ActivityModule {
    private Context mContext;
    public ActivityModule(Context context){
        mContext = context;
    }

    @PerActivity
    @Provides//必须提供Context对象,否则会报错
    public Context provideContext(){
        return mContext;
    }

}

接下来就是使用了,我们先在DemoApplication里面注解,

public class DemoApplication extends Application {
    @Inject
     LocationManager locationManager;//不能使用private修饰
     ApplicationComponent applicationComponent;
    private DemoApplication application;
    @Override
    public void onCreate() {
        super.onCreate();
        applicationComponent = DaggerApplicationComponent.builder().androidModule(new AndroidModule(this)).build();
        applicationComponent.inject(this);
        application = this;
    }
    public ApplicationComponent getComPonent(){
        return applicationComponent;
    }
}

然后在MainActivity里面依赖

   mainActivityComponent = DaggerMainActivityComponent.builder().activityModule(new ActivityModule(this))
                .applicationComponent(((DemoApplication) getApplication()).getComPonent()).build();
        mainActivityComponent.inject(this);

使用八(Qualifier)

通过自定义Qulifier,可以告诉Dagger2去需找具体的依赖提供者

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

然后在Module中我们这样写

   @ForBoy//根据不同注释,返回不同对象
    @Provides
    UserModel provideBoy(){
        return new UserModel("boy");
    }

    @ForGirl
    @Provides
    UserModel provideGirl(){
        return new UserModel("girl");
    }

具体使用

public class MainActivity extends AppCompatActivity {
    @ForBoy
    @Inject
    UserModel boy;
    @ForGirl
    @Inject //接收Inject或者Providers
    UserModel girl;
    private MainActivityComponent mainActivityComponent;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView  = (TextView) findViewById(R.id.textview);
         mainActivityComponent = DaggerMainActivityComponent.builder().activityModule(new ActivityModule(this))
                .applicationComponent(((DemoApplication) getApplication()).getComPonent()).build();
        mainActivityComponent.inject(this);
        textView.setText(boy.name+"\n"+girl.name);
    }
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值