Annotation注解APT(四):依赖注入框架Dagger
来源:互联网 发布:普通用户 linux 知乎 编辑:程序博客网 时间:2024/06/08 17:58
引言
通过前面的(http://blog.csdn.net/xuewend/article/details/73511128)文章,知道了注解的作用,其中一种就是做依赖注入,dagger是依赖注入的一种框架,那么如何来使用dagger框架呢?
Android Studio中的配置
top build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.3' //添加apt插件 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }}allprojects { repositories { jcenter() }}task clean(type: Delete) { delete rootProject.buildDir}
app build.gradle
//添加apt注解插件apply plugin: 'com.neenbedankt.android-apt'dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha7' testCompile 'junit:junit:4.12' //添加dagger依赖的库,当前版本为2.4 compile 'com.google.dagger:dagger:2.4' apt 'com.google.dagger:dagger-compiler:2.4'}
实例
package com.example.fishmov.daggerdemo;import javax.inject.Inject;/** * Created by fishmov on 17-6-21. */public class People { private String name = ""; @Inject public People() { } public String getName() { return name; } public void setName(String name) { this.name = name; }}
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @Inject People people; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(TAG, "onCreate: " + people); }}
直接运行,结果为:
06-21 15:35:36.818 26506-26506/com.example.fishmov.daggerdemo I/fish—: onCreate: null
因为我们目前的@Inject只是一个注解,并没有解析器来解析它,所以加不加一样,people没有初始化当然为空.
我们的目的是通过dagger框架在MainActivity自动注入依赖的People实例,要实现这个还需要一个桥梁Componet,通过Componet来注入:
package com.example.fishmov.daggerdemo;import dagger.Component;/** * Created by fishmov on 17-6-21. */@Componentpublic interface MainComponet { //定义注入的方法,表示支持对某个类的注入 void inject(MainActivity activity);}
记得rebuild一下,将自动生成Dagger+MainComponet一个类.
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @Inject People people; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(TAG, "onCreate: " + people); DaggerMainComponet.builder().build().inject(this); Log.i(TAG, "onCreate: " + people); }}
直接运行,结果为:
com.example.fishmov.daggerdemo I/fish—: onCreate: null
com.example.fishmov.daggerdemo I/fish—: onCreate: com.example.fishmov.daggerdemo.People@9af3aad
可以看到,调用dagger注入后,people实例化了一个对象.这种注入方式是最基本的注入方式,
然而这并没有什么卵用.
通过这种方式注入,需要在类的构造方法中添加@Inject注解,有时候我们无法修改别人的构造方法的时候,要如何使用注入呢?这个时候就需要@Module和@Provides注解了.
实例
package com.example.fishmov.daggerdemo;import javax.inject.Inject;/** * Created by fishmov on 17-6-21. */public class People { private String name = ""; public People() { } public String getName() { return name; } public void setName(String name) { this.name = name; }}
package com.example.fishmov.daggerdemo;import dagger.Component;/** * Created by fishmov on 17-6-21. */@Component(modules = MainModule.class)public interface MainComponet { //定义注入的方法,表示支持对某个类的注入 void inject(MainActivity activity);}
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @Inject People people; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(TAG, "onCreate: " + people); DaggerMainComponet.builder().mainModule(new MainModule()).build().inject(this); Log.i(TAG, "onCreate: " + people); }}
直接运行输出:
I/fish—: onCreate: null
I/fish—: onCreate: com.example.fishmov.daggerdemo.People@9af3aad
整个过程可以归纳为以下步骤:
- Activity中通过DaggerXXXComponent的Inject()触发注入过程;
- Dagger在Activity中搜索用@Inject标注的变量,说明该对象需要被注入;
- 去Component中注册的Module中搜索注入类;
- 在Module中搜索返回值为注入类的方法,执行并拿到注入类对象,从而完成注入过程;
- 如果在Module中没有搜索到提供目标类注入的方法,则在工程中搜索目标类;
- 找到需要注入对象后,寻找该对象中用@Inject标识的构造方法,完成自动创建过程.
如果People类的构造方法需要参数怎么办?如下:
package com.example.fishmov.daggerdemo;import javax.inject.Inject;/** * Created by fishmov on 17-6-21. */public class People { private String name = ""; public People(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
package com.example.fishmov.daggerdemo;import dagger.Module;import dagger.Provides;/** * Created by fishmov on 17-6-21. */@Module //提供依赖对象的实例public class MainModule { @Provides // 关键字,标明该方法提供依赖对象 People providerPerson(String name){ //提供Person对象 return new People(name); } @Provides String providerName(){ return "zhangsan"; } //或者使用这种 //@Provides // 关键字,标明该方法提供依赖对象 //People providerPerson(){ //提供Person对象 // return new People("zhangsan"); //}}
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @Inject People people; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(TAG, "onCreate: " + people); DaggerMainComponet.builder().mainModule(new MainModule()).build().inject(this); Log.i(TAG, "onCreate: " + people.getName()); }}
直接运行输出:
I/fish—: onCreate: null
I/fish—: onCreate: zhangsan
如果想注入同一对象的多个实例怎么办?这个时候就需要
@Named
package com.example.fishmov.daggerdemo;import javax.inject.Named;import dagger.Module;import dagger.Provides;/** * Created by fishmov on 17-6-21. */@Module //提供依赖对象的实例public class MainModule { @Named("a") @Provides // 关键字,标明该方法提供依赖对象 People providerPersonA(){ //提供Person对象 return new People("张三"); } @Named("b") @Provides // 关键字,标明该方法提供依赖对象 People providerPersonB(){ //提供Person对象 return new People("李四"); }}
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;import javax.inject.Named;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @Named("a") @Inject People peopleA; @Named("b") @Inject People peopleB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerMainComponet.builder().mainModule(new MainModule()).build().inject(this); Log.i(TAG, "onCreate: " + peopleA.getName()); Log.i(TAG, "onCreate: " + peopleB.getName()); }}
运行结果:
I/fish—: onCreate: 张三
I/fish—: onCreate: 李四
@Named注解表示采用使用module中的哪个provides,看看@Named的代码:
@Qualifier@Documented@Retention(RUNTIME)public @interface Named { /** The name. */ String value() default "";}
可以看出value是String类型的,前面学过如何自定义注解(http://blog.csdn.net/xuewend/article/details/73507725),我们也可以自定义一个,来达到和@Named一样的效果,关键字段
@Qualifier
package com.example.fishmov.daggerdemo;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import javax.inject.Qualifier;import static java.lang.annotation.RetentionPolicy.RUNTIME;/** * Created by fishmov on 17-6-21. */@Qualifier@Documented@Retention(RUNTIME)public @interface MType { int value() default -1;}
package com.example.fishmov.daggerdemo;import javax.inject.Named;import dagger.Module;import dagger.Provides;/** * Created by fishmov on 17-6-21. */@Module //提供依赖对象的实例public class MainModule { @MType(1) @Provides // 关键字,标明该方法提供依赖对象 People providerPersonA(){ //提供Person对象 return new People("张三"); } @MType(2) @Provides // 关键字,标明该方法提供依赖对象 People providerPersonB(){ //提供Person对象 return new People("李四"); }}
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;import javax.inject.Named;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @MType(1) @Inject People peopleA; @MType(2) @Inject People peopleB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerMainComponet.builder().mainModule(new MainModule()).build().inject(this); Log.i(TAG, "onCreate: " + peopleA.getName()); Log.i(TAG, "onCreate: " + peopleB.getName()); }}
运行结果不变.
@Singleton注解
如果我们把peopleB peopleA都注解为@MType(1)
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;import javax.inject.Named;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @MType(1) @Inject People peopleA; @MType(1) @Inject People peopleB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerMainComponet.builder().mainModule(new MainModule()).build().inject(this); Log.i(TAG, peopleA.getName() + peopleA); Log.i(TAG, peopleB.getName() + peopleB); }}
运行效果:
I/fish—: 张三com.example.fishmov.daggerdemo.People@9af3aad
I/fish—: 张三com.example.fishmov.daggerdemo.People@24ae1e2
可以看出,名字一样,但是地址不同,如果在module中添加@Singleton
package com.example.fishmov.daggerdemo;import javax.inject.Named;import javax.inject.Singleton;import dagger.Module;import dagger.Provides;/** * Created by fishmov on 17-6-21. */@Module //提供依赖对象的实例public class MainModule { @Singleton @MType(1) @Provides // 关键字,标明该方法提供依赖对象 People providerPersonA(){ //提供Person对象 return new People("张三"); } @MType(2) @Provides // 关键字,标明该方法提供依赖对象 People providerPersonB(){ //提供Person对象 return new People("李四"); }}
同样,这里也要添加@Singleton
package com.example.fishmov.daggerdemo;import javax.inject.Singleton;import dagger.Component;/** * Created by fishmov on 17-6-21. */@Singleton@Component(modules = MainModule.class)public interface MainComponet { //定义注入的方法,表示支持对某个类的注入 void inject(MainActivity activity);}
MainActivity不变,直接运行输出:
I/fish—: 张三com.example.fishmov.daggerdemo.People@9af3aad
I/fish—: 张三com.example.fishmov.daggerdemo.People@9af3aad
可以看出地址一样,这就是单例.
但是单例是有作用范围的,比如:
package com.example.fishmov.daggerdemo;import javax.inject.Singleton;import dagger.Component;/** * Created by fishmov on 17-6-21. */@Singleton@Component(modules = MainModule.class)public interface MainComponet { //定义注入的方法,表示支持对某个类的注入 void inject(MainActivity activity); //定义注入的方法,表示支持对某个类的注入 void inject(MainActivity.House house);}
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;import javax.inject.Named;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @MType(1) @Inject People peopleA; @MType(1) @Inject People peopleB; MainModule mainModule; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainModule = new MainModule(); DaggerMainComponet.builder().mainModule(mainModule).build().inject(this); Log.i(TAG, peopleA.getName() + peopleA); Log.i(TAG, peopleB.getName() + peopleB); new House(); } class House{ @MType(1) @Inject People peopleA; @MType(1) @Inject People peopleB; public House() { DaggerMainComponet.builder().mainModule(mainModule).build().inject(this); Log.i(TAG + "House", peopleA.getName() + peopleA); Log.i(TAG + "House", peopleB.getName() + peopleB); } }}
结果输出:
I/fish—: 张三com.example.fishmov.daggerdemo.People@e7e1ddb
I/fish—: 张三com.example.fishmov.daggerdemo.People@e7e1ddb
I/fish—House: 张三com.example.fishmov.daggerdemo.People@b2da078
I/fish—House: 张三com.example.fishmov.daggerdemo.People@b2da078
可以看出,同一个Componet注入的地址一样,不同的地址不一样,这叫做假单例,那如何做到全局的单例呢?
package com.example.fishmov.daggerdemo;import android.app.Application;/** * Created by fishmov on 17-6-21. */public class MyApplication extends Application { private static MainComponet mainComponet; @Override public void onCreate() { super.onCreate(); mainComponet = DaggerMainComponet.builder().mainModule(new MainModule()).build(); } public static MainComponet getMainComponet() { return mainComponet; }}
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.fishmov.daggerdemo"> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
package com.example.fishmov.daggerdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import javax.inject.Inject;import javax.inject.Named;public class MainActivity extends AppCompatActivity { private static final String TAG = "fish---"; @MType(1) @Inject People peopleA; @MType(1) @Inject People peopleB; MainModule mainModule; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyApplication.getMainComponet().inject(this); Log.i(TAG, peopleA.getName() + peopleA); Log.i(TAG, peopleB.getName() + peopleB); new House(); } class House{ @MType(1) @Inject People peopleA; @MType(1) @Inject People peopleB; public House() { MyApplication.getMainComponet().inject(this); Log.i(TAG + "House", peopleA.getName() + peopleA); Log.i(TAG + "House", peopleB.getName() + peopleB); } }}
结果输出:
I/fish—: 张三com.example.fishmov.daggerdemo.People@9af3aad
I/fish—: 张三com.example.fishmov.daggerdemo.People@9af3aad
I/fish—House: 张三com.example.fishmov.daggerdemo.People@9af3aad
I/fish—House: 张三com.example.fishmov.daggerdemo.People@9af3aad
可以看出地址一样了
@Scope注解
@Scope注解相对于@Singleton,和@Qualifier相对于@Named一样,
看源码:
@Scope@Documented@Retention(RUNTIME)public @interface Singleton {}
所以我们也可以通过@Scope自定义一个注解功能和@Singleton一样.
好了,就到这里吧,其实没有什么卵用.
参考:
http://blog.csdn.net/lylodyf/article/details/52981910?locationNum=8&fps=1
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0528/4307.html
https://wenku.baidu.com/view/9b6be73515791711cc7931b765ce0508763275cd.html?from=search
- Annotation注解APT(四):依赖注入框架Dagger
- Annotation注解APT(三):依赖注入是什么
- Annotation注解APT(五):注入框架ButterKnife
- Android 依赖注入(DI)框架 Dagger
- Android Dagger依赖注入框架浅析
- Android Dagger依赖注入框架浅析
- Android 依赖注入框架 Dagger 学习
- Android Dagger依赖注入框架浅析
- Android Dagger依赖注入框架浅析
- Android Dagger依赖注入框架浅析
- spring annotation注解 依赖注入
- 依赖注入?Dagger?
- Dagger,ButterKnife,Roboguide,AndroidAnnotations框架的依赖注入浅析
- Dagger——Android的依赖注入框架
- android依赖注入框架Dagger和Butterknife实战
- Android开源框架——依赖注入Dagger
- 【Annotation】使用自定义注解实现依赖注入
- 07 Spring框架 依赖注入(四)基于注解的依赖注入
- activity里面fragment见的跳转
- hdoj1097 A hard puzzle(简单题)
- eval的作用
- Android Design风格组件之BottomSheets
- 欢迎使用CSDN-markdown编辑器
- Annotation注解APT(四):依赖注入框架Dagger
- @+id/和android:id有什么区别?
- JSON字符串与JSON对象的区别
- 【Python】下载图片的代码
- 变量的命名2
- fragment返回键处理
- unity委托的排序方法
- NYOJ 28 大数阶乘
- android内存泄漏解决方案