【Android】Dagger2从入门到再入门(进阶)
2016-12-11 14:54
375 查看
上一篇【Android】Dagger2从入门到再入门讲解了dagger2的基本使用方式,本篇介绍一下@Named,@Singleton,@Scope等其它注解的使用方式;
1.我们在MainActivity里注入两个Student对象(接着上篇讲的,不明白的可以简单浏览下上一篇文章):
2.打印一下这两个对象:
3.结果:
嗯,记过很棒,确实是两个对象,但是我们如果想实现单例模式该怎么办呢,我们有时需要在不同的页面使用同一个实例,这时候@Singleton就能帮上忙了,@Singleton这个注解的作用就是声明单例模式,下面我们来验证一下:
4.StudentMoudle中提供Student实例的地方添加@Singleton注解:
5.在StudentComponent注入器类的上方添加@Singleton注解,然后编译运行:
结果:
我们发现,确实实现了单例模式,是不是很简单;
1.我们在StudentMoudle中再添加一个提供Student实例的provideOtherStudent方法,如下:
此时编译的话,会报如下错误:
意思是说我们不能提供多个返回参数是一样实例的方法,因为dagger是根据返回类型来提供实例的,那么我们该怎么办呢?
2.这个时候就需要使用一个标记来指定需要使用哪个方法来提供实例,@Named就是干这个的了,我们加上@Named注解:
3.在注入的地方指定需要哪个对象,然后打印Student的名字:
结果如下,运行成功,分别创建了自己需要的对象:
这里说一下@Qulifier注解,@Qulifier功能和@Named一样,并且@Named就是使用@Qulifier来定义的,@Named的源码如下:
这下大家明白了吧,这个@Named可以随意定义,功能都是一样的,只是名字不同罢了,大家可以尝试下自己定义,然后使用方式和@Named一样,这里就不多说了;
→→ 源码里对Scope的解释比较多,这里我们留下了第一段话,就是上面的一大串英文,大概意思就是说,@Scope注解是标识作用域的,意思就是说你在@Provides处使用了@Scope相关联的注解,就必须在注入类使用同样的注解标识作用范围,另外如果使用了@Scope注解,实例的创建就是单例模式,如果不使用,每次都会创建一个新的对象,单例?说到这你应该想到了上面@Singleton注解,来看下@Singleton的源码:
我们发现了@Scope的身影,这下明白了吧,@Singleton的单例其实是@Scope的作用,我们来看个简单的例子:
1.新建School类
2.自定义Scope注解
3.创建module和component,使用@MainScope注解
4.新建了SecondActivity,注入School对象,编译,运行
结果:
注意:在同一个作用范围内,Provide方法提供的依赖对象就会变成单例,也就是说依赖需求方不管依赖几次Provide方法提供的依赖对象,Dagger2都只会调用一次这个方法;
参考连接:
1.Dagger2 入门
2.http://stackoverflow.com/questions/30260073/dagger-2-error-dependency-cannot-be-provided-without-an-inject-constructor-w
一.@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
相关文章推荐
- 【Android 进阶】Dagger2 系列:入门案例一
- Text-to-speech 入门与进阶学习笔记(android)
- Android入门进阶教程(2)-windows 开发环境的搭建
- Android入门进阶教程(18)- Looper、MessageQueue、Handler 与消息循环
- Android入门进阶教程(23)-内存中读/取数据
- Android入门进阶教程(22)-系统广播 BroadcastReceiver详解
- Android移动开发入门与进阶
- Android入门进阶教程(4)-android hello world开发
- Android入门进阶教程(16)-ActivityThead、ActivityManagerService 详解
- Android入门进阶教程(15)-进程创建zygote 详解
- Android入门进阶教程(2)-windows 开发环境的搭建
- Android入门进阶教程(3)-linux 开发环境的搭建
- Android入门进阶教程(8)-常用组件 打电话,发短信简单应用 &单元测试
- Android入门进阶教程(7)-常用组件 TabHost、Gallery
- Android入门进阶教程(17)-WindowManager 窗口管理介绍
- Android入门进阶教程(1)-android扫盲
- Android入门进阶教程(6)-常用组件 ListView、GridView
- Android入门进阶教程(10)-Xml解析
- Android入门进阶教程(20)-ContentProvider 数据共享
- Android入门进阶教程(3)-linux 开发环境的搭建