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都只会调用一次这个方法;
参考连接:
以上是关于AndroidDagger2从入门到再入门(进阶)的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server AlwaysON从入门到进阶——何为AlwaysON?
Kotlin基础从入门到进阶系列讲解(入门篇)Activity的使用