AndroidDagger2从入门到再入门(进阶)

Posted 寒小枫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AndroidDagger2从入门到再入门(进阶)相关的知识,希望对你有一定的参考价值。

上一篇【Android】Dagger2从入门到再入门讲解了dagger2的基本使用方式,本篇介绍一下@Named,@Singleton,@Scope等其它注解的使用方式;

一.@Singleton

先看个例子:

1.我们在MainActivity里注入两个Student对象(接着上篇讲的,不明白的可以简单浏览下上一篇文章):

@Inject
Student student;

@Inject
Student studentTwo;

2.打印一下这两个对象:

tvOne = (TextView) findViewById(R.id.tv_one);
tvTwo = (TextView) findViewById(R.id.tv_two);
tvOne.setText(""+student);
tvTwo.setText(""+studentTwo);

3.结果:

嗯,记过很棒,确实是两个对象,但是我们如果想实现单例模式该怎么办呢,我们有时需要在不同的页面使用同一个实例,这时候@Singleton就能帮上忙了,@Singleton这个注解的作用就是声明单例模式,下面我们来验证一下:

4.StudentMoudle中提供Student实例的地方添加@Singleton注解:

@Module
public class StudentMoudle 

    @Singleton
    @Provides
    public Student provideIStudent()
    
        Student student = new Student();
        student.setName("张三");
        student.setSayStr("一天不装逼,浑身难受");
        return student;
    

5.在StudentComponent注入器类的上方添加@Singleton注解,然后编译运行:

@Singleton
@Component(modules = StudentMoudle.class)
public interface StudentComponent 
    void inject(MainActivity activity);

结果:

我们发现,确实实现了单例模式,是不是很简单;

二.@Named

再来看个例子:

1.我们在StudentMoudle中再添加一个提供Student实例的provideOtherStudent方法,如下:

@Module
public class StudentMoudle 

    @Singleton
    @Provides
    public Student provideIStudent()
    
        Student student = new Student();
        student.setName("张三");
        student.setSayStr("一天不装逼,浑身难受");
        return student;
    


    @Singleton
    @Provides
    public Student provideOtherStudent()
    
        Student student = new Student();
        student.setName("李四");
        student.setSayStr("我是帅哥我怕谁");
        return student;
    

此时编译的话,会报如下错误:

意思是说我们不能提供多个返回参数是一样实例的方法,因为dagger是根据返回类型来提供实例的,那么我们该怎么办呢?

2.这个时候就需要使用一个标记来指定需要使用哪个方法来提供实例,@Named就是干这个的了,我们加上@Named注解:

@Singleton
@Named("zhang")
@Provides
public Student provideIStudent()

    Student student = new Student();
    student.setName("张三");
    student.setSayStr("一天不装逼,浑身难受");
    return student;
 


@Singleton
@Named("li")
@Provides
public Student provideOtherStudent()

    Student student = new Student();
    student.setName("李四");
    student.setSayStr("我是帅哥我怕谁");
    return student;

3.在注入的地方指定需要哪个对象,然后打印Student的名字:

@Inject
@Named("zhang")
Student student;

@Inject
@Named("li")
Student studentTwo;
tvOne = (TextView) findViewById(R.id.tv_one);
tvTwo = (TextView) findViewById(R.id.tv_two);
tvOne.setText(""+student+"--student name = "+student.getName());
tvTwo.setText(""+studentTwo+"--student name = "+studentTwo.getName());

结果如下,运行成功,分别创建了自己需要的对象:

这里说一下@Qulifier注解,@Qulifier功能和@Named一样,并且@Named就是使用@Qulifier来定义的,@Named的源码如下:

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named 

    /** The name. */
    String value() default "";

这下大家明白了吧,这个@Named可以随意定义,功能都是一样的,只是名字不同罢了,大家可以尝试下自己定义,然后使用方式和@Named一样,这里就不多说了;

三.@Scope

font size=”4” color=”#535346”>我们先来看下@Scope的源码:

/**
 * Identifies scope annotations. A scope annotation applies to a class
 * containing an injectable constructor and governs how the injector reuses
 * instances of the type. By default, if no scope annotation is present, the
 * injector creates an instance (by injecting the type's constructor), uses
 * the instance for one injection, and then forgets it. If a scope annotation
 * is present, the injector may retain the instance for possible reuse in a
 * later injection. If multiple threads can access a scoped instance, its
 * implementation should be thread safe. The implementation of the scope
 * itself is left up to the injector.
 */
@Target(ANNOTATION_TYPE)
@Retention(RUNTIME)
@Documented
public @interface Scope 

→→ 源码里对Scope的解释比较多,这里我们留下了第一段话,就是上面的一大串英文,大概意思就是说,@Scope注解是标识作用域的,意思就是说你在@Provides处使用了@Scope相关联的注解,就必须在注入类使用同样的注解标识作用范围,另外如果使用了@Scope注解,实例的创建就是单例模式,如果不使用,每次都会创建一个新的对象,单例?说到这你应该想到了上面@Singleton注解,来看下@Singleton的源码:

/**
 * Identifies a type that the injector only instantiates once. Not inherited.
 *
 * @see javax.inject.Scope @Scope
 */
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton 

我们发现了@Scope的身影,这下明白了吧,@Singleton的单例其实是@Scope的作用,我们来看个简单的例子:

1.新建School类

public class School 

    private String schoolName;

    public School() 
    

    public School(String schoolName) 
        this.schoolName = schoolName;
    

    public String getSchoolName() 
        return schoolName;
    

    public void setSchoolName(String schoolName) 
        this.schoolName = schoolName;
    

2.自定义Scope注解

@Scope
@Retention(RUNTIME)
public @interface MainScope 

3.创建module和component,使用@MainScope注解

@Module
public class SchoolMoudle 

    @MainScope
    @Provides
    public School provideISchool()
    
        School school = new School();
        school.setSchoolName("清华大学");
        return school;
    

@Component(modules = SchoolMoudle.class)
@MainScope
public interface SchoolComponent 
    void inject(SecondActivity activity);

4.新建了SecondActivity,注入School对象,编译,运行

public class SecondActivity extends AppCompatActivity 

    private Button button;

    @Inject
    School school;

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

        initInject();
        initView();
    

    private void initView() 
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                Toast.makeText(SecondActivity.this, "school name = "+school.getSchoolName(), Toast.LENGTH_SHORT).show();
            
        );
    

    private void initInject() 
        DaggerSchoolComponent.builder().schoolMoudle(new SchoolMoudle()).build().inject(this);
    



结果:

注意:在同一个作用范围内,Provide方法提供的依赖对象就会变成单例,也就是说依赖需求方不管依赖几次Provide方法提供的依赖对象,Dagger2都只会调用一次这个方法;

参考连接:

1.Dagger2 入门

2.http://stackoverflow.com/questions/30260073/dagger-2-error-dependency-cannot-be-provided-without-an-inject-constructor-w

以上是关于AndroidDagger2从入门到再入门(进阶)的主要内容,如果未能解决你的问题,请参考以下文章

Nmap从入门到再入门

SQL Server AlwaysON从入门到进阶——何为AlwaysON?

Kotlin基础从入门到进阶系列讲解(入门篇)Activity的使用

Tornado从入门到进阶 打造支持高并发的技术论坛

Kotlin基础从入门到进阶系列讲解(入门篇) 文件存储的基本使用

Kotlin基础从入门到进阶系列讲解(入门篇)Activity的简介和使用