本文主要是介绍Dagger2的入坑指南[捂脸][详]!!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
dagger2的文章从寥寥可数到现在的数不胜数,可见其热门程度。
这篇文章主要是记录我对dagger2的理解,从基本使用,到实际运用,由浅入深。以及dagger2的一些变化。
希望大家能取其精华,去其糟粕,谢谢。
目录结构
-
- 前言
- 为什么要使用dagger2
- 从需求的角度
- 从开发者的角度
- 基本的使用
- inject
- Component
- Module
- Provides
- 基本使用总结
- 循循渐进的项目搭建
- Singleton
- Component dependencies
- 自定义Scope
- 项目搭建优化
- Binding Instances 构建方式
- Reusable Scope 作用域
- 扩展库daggeradnroid
- 其他注解
- Qualifier和Named
- Lazy 延迟注入
- SubComponent
- 总结
为什么要使用dagger2?
我想这是许多人的困惑。为什么不直接new一个对象。 而是通过配置各式各样的注解达到new的目的?看了许许多多的文章,都指向一个观点,一切是为了解耦。
从需求的角度
比如业务类UserService(UserApi api) . 需要构造这个函数。一开始实例化简单,但是随着业务的跟进你需要保存一些用户设置,构造函数加入SharedPreferences。
随着构造函数的数量不断增加,就会变得越来越累赘,并且又是多人合作,依赖别人写的对象。改起来你说麻烦不(TVT).这就是为什么dagger2适合大型的项目。
如果是小型项目,而且代码都是自己撸的。对于生命周期和使用的对象的依赖关系又比较熟悉,这时可以考虑不使用。当然如果业务类构造函数复杂且需要注入的对象多,不妨可以考虑考虑。
总的来说!对面这样的情况Dagger2维护起来就方便多了,可以使用一个moudule来维护。可以理解为仓库吧。总之就是维护多个仓库。里面提供所需要的实体对象。
直接在声明的时候
@Inject
UserService mUserService;
这时无论UserService 需要依赖多少对象.都ok.会自动去仓库去寻找自己所需要的构造对象。从而达到解耦的目的。
从开发者的角度
说实话,落后就要挨打。
基本的使用
依赖
compile 'com.google.dagger:dagger:2.12'annotationProcessor 'com.google.dagger:dagger-compiler:2.12'
先来一个最简单的需求。在activity实例化UserService业务类
通常做法:activity 直接new。
dagger2做法:最简单的注入。需要配合 @inject 与 @Component 注解构成。
不逼逼w(゚Д゚)w。直接 上代码说明
1 业务类。对构造函数进行声明标识,告诉Dagger。生成对象时可以使用这个构造方法。
public class UserService {@Inject //(1) UserService() {}//假设请求网络数据方法public void request(){}
}
2 还需要一个桥梁Component,和activity产生产生关系。
@Component
public interface MainComponent {//说明要在那个activity注入void inject(MainActivity mainActivity);
}
3.写好之后进行重构生成注入代码。
重构完后会生成一个DaggerMainComponent,提供注入,名字生成的规则是DaggerXXComponent。
最后在activity使用
public class MainActivity extends AppCompatActivity {@Inject//(2)要new那个。就inject那个。UserService mUserService;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//(3)注入DaggerMainComponent.builder().build().inject(this);Log.w(MainActivity.class.getSimpleName(),mUserService.toString());mUserService.request(); }
}
说明一下这两个注解的意思:
@inject
对构造函数进行声明,Dagger可以构建该类的实例。//(1)
对字段,也就是成员变量声明,就是告诉dagger2 我需要这个实例对象。//(2)
@Component
- 可以理解为桥梁,就是将它们联系起来。
这样就完成一个对象最简单的注入。
当然在实际的项目当中不可能那么简单。如果UserServic需要一个Gson,需要一个Retrofit,一些第三方的对象时,而你需要 @inject声明构造函数。去告诉dagger2要那个对象。在这些情况下是不可行,因为第三方类不能修改。
面对这种情况,就需要@Module注解和@Provides注解来描述依赖关系了。 去解决以上的问题了
需求改变:Userservic 需要一个Gson对象。
业务类的修改,假设UserService需要Gson对象
public class UserService {Gson gson;@Injectpublic UserService(Gson gson) {this.gson = gson;}public Gson getGson() {return gson;}public void request() {}}
这时如果要实例化Gson,按照上面的步骤来说,应该在Gson的构造函数标识@inject。才可以被实例化,由于无法做到,所以就只能声明Module仓库来提供Gson对象。
声明Module
@Module
public class UserModule {@ProvidesGson provideGson() {return new Gson();}// 如果有了module,可以把Userservic构造函数的@inject去掉.//依赖对象由module提供。// 如果没有去掉Userservic的inject并且也在module提供了实例、那么。//记住,@Module级别高于@Inject。/* @ProvidesUserService providesUserService(Gson gson) {return new UserService(gson);}
*/
}
@Module
- 注解的类表明它可以提供依赖对象,声明这是一个仓库。标识可以提供对象
@Provides
- 告诉Dagger我们想要构造对象并提供这些依赖
按照惯例,@Provides方法以provide开头,Module类以Module结尾。
修改Component,构建module的关系。
@Component(modules = UserModule.class)//可以有多个modules={xxxModule.class,XXclass,等等}
public interface MainComponent {void inject(MainActivity mainActivity);
}
最后在重新编译。在activity调用
DaggerMainComponent.builder().userModule(new UserModule()).build().inject(this);Gson gson = mUserService.getGson();Log.w(MainActivity.class.getSimpleName(), gson.getClass().toString());
有人会说如果Service需要的对象Context,module要怎么提供?
Userservic
@Injectpublic UserService(Gson gson, Context context) {this.gson = gson;this.context = context;}
Module可以通过构造函数去提供实例,并提供出去。
Context mContext;public UserModule(Context context) {this.mContext = context;}@ProvidesContext provideContext(){return mContext;}
最后编译,activity调用。
DaggerMainComponent.builder().userModule(new UserModule(this)).build().inject(this);
3 基本使用总结
如果能看懂上面的东西。大概就算是入门了吧。嗯嗯,基本操作。
接下来我们就慢慢扩充我们的需求。慢慢融入到我们的真实项目。
循循渐进的项目搭建
先看一段代码:
UserModule:很简单就提供一个Gson
@Module
public class UserModule {@ProvidesGson provideGson() {return new Gson();}}
Component
@Component(modules = UserModule.class)
public interface MainComponent {void inject(MainActivity mainActivity);
}
activity:注入2个Gson.
@InjectGson mGson1;@InjectGson mGson2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);DaggerMainComponent.builder().userModule(new UserModule()).build().inject(this);Log.w("MainActivity", Integer.toHexString(mGson1.hashCode()));Log.w("MainActivity", Integer.toHexString(mGson2.hashCode()));}
可以看到这是两个不同的对象
需求:
通常我们在项目中有对象需用频率过高,需要保持全局单例的情况,也就是达到复用的目的。例如全局的Application
,全局的OkHttpClient ,等等….。
通常做法:静态变量,或者单例模式封装,等…
Dagger2:使用@Singleton标识 保持单例,也可以使用自定义scope或者使用Reusable。先说说@Singleton
我们修改一下代码
module
@Provides@SingletonGson provideGson() {return new Gson();}
Component
@Singleton
@Component(modules = UserModule.class)
public interface MainComponent {void inject(MainActivity mainActivity);
}
activity 不改。看看结果
就是那么简单。
@Singleton
注意事项:
别想的太难,仅仅只标记而已,通过这个标记。dagger2获取实例的方法会生成单例。具体的可以看看生成后的源码
module提供对象的方法用@Singleton注解声明,其Component也要保持一致哦。不然会编译不通过。
- 除了上面要module和Component要使用同一个之外。想要要保证对象的全局单例,Component只能构建一次。比如:
A activity : Aactivity 注入 。
@inject
Gson gson;DaggerMainComponent.builder().userModule(new UserModule()).build().inject(this);
B Activity Bactivity 注入 。
@inject
Gson gson;DaggerMainComponent.builder().userModule(new UserModule()).build().inject(this);
其中A和B的Gson是不可能是同一个对象的,因为初始化的原因。所以要提供整个App的单例就必须保证初始化构建一次。
所有我们可以在自定义Application构建。
public class MyApplication extends Application {private DaggerMainComponent daggerMainComponent;@Overridepublic void onCreate() {super.onCreate();//构建daggerMainComponent= DaggerMainComponent.builder().userModule(new UserModule()).build();}public DaggerMainComponent getDaggerMainComponent() {return daggerMainComponent;}}
A activity 和 b activity 使用
MyApplication myApplication = (MyApplication) getApplication();myApplication.getDaggerMainComponent().inject(this);
这样就可以保持单例,从而达到复用的目的了
有了上面的的基础,我们可以搭建属于我们的第一个模块。
公共模块
让dagger2提供App全局所需要的对象
先搭建我们的公共仓库。
AppModule :最基础的,提供全局的Application 各位看情况而定
@Module
public class AppModule {Application mApplication;public AppModule(Application application) {mApplication = application;}@Provides@SingletonApplication providesApplication() {return mApplication;}@Provides@SingletonSharedPreferences providesSharedPreferences(Application application) {return PreferenceManager.getDefaultSharedPreferences(application);}
}
NetModule :公共网络请求,使用的是 retrofit2, 根据自己的情况搭建
@Module
public class NetModule {String mBaseUrl;// 构造module所需要的参数。根据每个人的情况而定public NetModule(String baseUrl) {this.mBaseUrl = baseUrl;}@Provides@SingletonCache provideOkHttpCache(Application application) {int cacheSize = 10 * 1024 * 1024; // 10 MiBreturn new Cache(application.getCacheDir(), cacheSize);}@Provides@SingletonGson provideGson() {GsonBuilder gsonBuilder = new GsonBuilder();gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);return gsonBuilder.create();}@Provides@SingletonHttpLoggingInterceptor provideHttpLoggingInterceptor() {HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);return interceptor;}@Provides@SingletonOkHttpClient provideOkHttpClient(HttpLoggingInterceptor httpLoggingInterceptor,Cache cache) {OkHttpClient.Builder builder = new OkHttpClient.Builder();builder.cache(cache).addInterceptor(httpLoggingInterceptor).connectTimeout(30, TimeUnit.SECONDS).writeTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS).build();return builder.build();}@Provides@SingletonRetrofit provideRetrofit(Gson gson, OkHttpClient mOkHttpClient) {return new Retrofit.Builder().baseUrl(mBaseUrl).client(mOkHttpClient).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create(gson)).build();}}
基础的module搭好后,关联 Component
@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface AppComponent {void inject(MyApplication application);
}
最后一步,重新编译。然后使用
public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();DaggerAppComponent.builder().appModule(new AppModule(this)).netModule(new NetModule("www.github.com")).build().inject(this);}
}
这时候你可能会困惑,你在MyApplication注入用处不大 ,难道要在这里进行网络请求么?当然如果有需要实例化的对象也可以注入。
如果AMainActivity,BMainActivity 需要用到这些公共对象该怎么做?
很简单,在Component关联上不就行了吗?
@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface AppComponent {void inject(MyApplication application);void inject(AMainActivity activity);void inject(BMainActivity activity);
}
这样做也行,如果按照上面的这样做,你必须要在 A和B的activity去构建注入才可以获取到这些对象,但是这些对象就不是单例的了。
就忘了最初的考虑。想要保证全局单例,Component只能构建一次,
所以MyApplication 要提供出Component,并且保证构建一次。
修改如下
public class MyApplication extends Application {private AppComponent mAppComponent;@Overridepublic void onCreate() {super.onCreate();mAppComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).netModule(new NetModule("www.github.com")).build();}public AppComponent getAppComponent() {return mAppComponent;}}
AMainActivity
@InjectRetrofit mRetrofit;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);((MyApplication)getApplication()).getAppComponent().inject(this);Log.w("AMainActivity", mRetrofit.toString());findViewById(R.id.tv_text2).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(AMainActivity.this,BMainActivity.class));}});}
BMainActivity
@InjectRetrofit mRetrofit;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);((MyApplication)getApplication()).getAppComponent().inject(this);Log.w("BMainActivity", mRetrofit.toString());//((MyApplication)getApplication()).getAppComponent().inject();}
这样就保证了
虽然这样可以保证全局的唯一性。但是随着activity的增多,可能每个activity用到的module都不一样,也就是需要注入的对象不同。
@Singleton
@Component(modules = {AppModule.class, NetModule.class,BModule.class,AModule.class,XModule.class,.....Module.class})
public interface AppComponent {void inject(MyApplication application);void inject(AMainActivity activity);void inject(BMainActivity activity);void inject(XMainActivity activity);......
}
一个Component堆多了module看着也不舒服。就像整个项目没有BaseActivity一样.你觉得合理么?
所以下面介绍一下Component dependencies ,和自定义Scope。
@Component dependencies
很简单,直接看代码。
假设我们AMainActivity 需要Amodule 提供业务对象。各位根据实际情况而定
@Module
public class AModule {@ProvidesUserService providesUserService(){return new UserService();}
}
我们新建一个ActivityComponent 统筹所有的Activity.
@Component(modules = {AModule.class}, dependencies = AppComponent.class)//可以依赖多个Component
public interface ActivityComponent {void inject(AMainActivity aMainActivity);
}
注意:
可以看到 我们的 Component 加上了dependencies 并且继承与AppComponent。
这时候要注意了。如果现在进行编译的话会编译不通过。
这里有个规则。
如果依赖的Component需要用到父Component的对象,必须要父Component通过方法提供出来。
所以, AppComponent 修改如下
@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface AppComponent {//暴露出子Component 需要的对象。各位根据直接的情况而定。//gsonGson gson();Application application();OkHttpClient okHttpClient();SharedPreferences sharedPreferences();Retrofit retrofit();void inject(MyApplication application);void inject(BMainActivity bMainActivity);
}
这时候在编译就会出现以下问题。
大概的意思是没有scope的不能依赖有scope的组件,也就是说你的Component要有一个Scope修饰
然后你在ActivityComponent 加上@Singleton标识还是上面那个提示。
这时候注意了。
@Component的dependencies与@Component自身的scope不能相同。
可以通过自定义Scope来解决上面的问题,这算是自定义Scope的场景使用之一。
自定义Scope
在看别人的项目的时候通常会看到两个Scope,ActivityScope 跟 FragmentSopce。 (也有可能其他命名。随意)
如其字义,好理解,使用于Activity和fragment。
废话不多说,直接仿写 @Singleton。
ActivityScope
@Scope
@Documented
@Retention(RUNTIME)
public @interface ActivityScope {}
FragmentScope 和上面的一样,改个名字即可。
然后在我们的ActivityComponent修改如下
@ActivityScope
@Component(modules = {AModule.class}, dependencies = AppComponent.class)
public interface ActivityComponent {void inject(AMainActivity aMainActivity);
}
当然,如果想依赖的Module也希望提供单例的话,这时也可以加上@ActivityScope即可
@Module
public class AModule {@Provides@ActivityScopeUserService providesUserService(){return new UserService();}
}
最后编译即可。
AMainActivitty
//((MyApplication)getApplication()).getAppComponent().inject(this);DaggerActivityComponent.builder().appComponent(((MyApplication)getApplication()).getAppComponent()).build().inject(this);
如果是在fragment里使用呢?和上面几乎没啥区别
@FragmentScope
@Component(modules = XXModule.class,....XXModule.class, dependencies = AppComponent.class)
public interface FragmentComponent {void inject(XXFragment fragment);// .....inject...
}
最后编译使用即可。
也许上面所搭建方式的会与其他人的有所不同。
有些人是 一个模块 对应着一个Component和module。
在github上随便找的项目截图
activity
fragment
项目dagger2结构
这样做也行,但是会写比较多的 Component和module。
我就是懒一点。直接2个Component统筹全局。当然,这不是重点。
重要的是怎么理解这些知识点。正所谓万变不离其宗。
项目的基本搭建就到此结束了。接下来是一些优化和其他相关注解。
项目搭建优化
Binding Instances 构建方式
我们可以看到上面搭建的module。如果需要特定的参数,有种方法是通过构造函数进行注入。
比如上面的NetModule
// 构造module所需要的参数。根据每个人的情况而定public NetModule(String baseUrl) {this.mBaseUrl = baseUrl;}
也可以通过Component来提供,清晰。
我们就拿上面所写的两个module作为例子修改。优化
新建AppModule2
@Module
public class AppModule2 {/*由于要改为由Component提供参数,所以这里注释掉
Application mApplication;public AppModule2(Application application) {mApplication = application;}@Provides@SingletonApplication providesApplication() {return mApplication;}*/@Provides@SingletonSharedPreferences providesSharedPreferences(Application application) {return PreferenceManager.getDefaultSharedPreferences(application);}}
NetModule2
@Module
public class NetModule2 {/*改为由Component提供!String mBaseUrl;// 构造module所需要的参数。根据每个人的情况而定public NetModule2(String baseUrl) {this.mBaseUrl = baseUrl;}*///.. 省略//把mBaseUrl 作为参数传入@Provides@SingletonRetrofit provideRetrofit(Gson gson, OkHttpClient mOkHttpClient,String mBaseUrl) {return new Retrofit.Builder().baseUrl(mBaseUrl).client(mOkHttpClient).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create(gson)).build();}
}
最后Component
@Singleton
@Component(modules = {AppModule2.class, NetModule2.class})
public interface AppComponent2 {@Component.Builder interface Builder {// Module所需要的参数可以这样提供@BindsInstance Builder application(Application application);@BindsInstance Builder baseUrl(String baseUrl);AppComponent2 build();}//gsonGson gson();Application application();OkHttpClient okHttpClient();SharedPreferences sharedPreferences();Retrofit retrofit();void inject(MyApplication application);void inject(BMainActivity bMainActivity);
}
使用
DaggerAppComponent2.builder().application(this).baseUrl("https://api.xxx.com/").build().inject(this);
Reusable Scope 作用域
在上面我们使用到了Singleton 和 自定义了 activityScope 和 fragmentScope。定义他们的原因可以复用对象,并且可以保证局部单例。
假如你仅仅是需要缓存依赖的实例,达到复用的效果。且不需要那么多的scope约束。可以考虑用这个替换。
Reusable 作用域不关心绑定的 Component,只需要标记目标类或 provide 方法即可。
项目作用域优化,重新修改一下module
- 把module中Provides下面的Singleton替换为Reusable
- 删除component上面的Scope
AppModule2
@Module
public class AppModule2 {@Provides@Reusable //替换原来ScopeSharedPreferences providesSharedPreferences(Application application) {return PreferenceManager.getDefaultSharedPreferences(application);}
}
NetModule2(略)
意思和上面一样,替换即可。
Component 把Scope删除即可
@Component(modules = {AppModule2.class, NetModule2.class})
public interface AppComponent2 {
@Component.Builder interface Builder {// Module所需要的参数可以这样提供@BindsInstance Builder application(Application application);@BindsInstance Builder baseUrl(String baseUrl);AppComponent2 build();}//gsonGson gson();Application application();OkHttpClient okHttpClient();SharedPreferences sharedPreferences();Retrofit retrofit();void inject(MyApplication application);}
子Component,一样Scope删除即可,这里的依赖module各位自己定。
@Component( dependencies = AppComponent2.class)
public interface ActivityComponent2 {void inject(Di2Activity di2Activity);void inject(Di2Activity2 di2Activity);
}
在MyApplication 提供ActivityComponent2实例。
private AppComponent2 mAppComponent2;@Overridepublic void onCreate() {super.onCreate();mAppComponent2 = DaggerAppComponent2.builder().application(this).baseUrl("https://api.xxx.com/").build();}public AppComponent2 getAppComponent2() {return mAppComponent2;}
然后 使用测试打印
Di2Activity
@InjectRetrofit mRetrofit;MyApplication myApplication = (MyApplication) getApplication();DaggerActivityComponent2.builder().appComponent2(myApplication.getAppComponent2()).build().inject(this);Log.w("Di2Activity",mRetrofit.toString());
Di2Activity2
@InjectRetrofit mRetrofit;MyApplication myApplication = (MyApplication) getApplication();DaggerActivityComponent2.builder().appComponent2(myApplication.getAppComponent2()).build().inject(this);Log.w("Di2Activity2",mRetrofit.toString());
查看结果
这样就保证了对象的复用了
扩展库dagger.adnroid
为什么会出现这个扩展库呢?英文好大的大兄弟可以去看官网的介绍Dagger.android。
不好的话 那只能看我吹牛逼 简单的翻译了。
如果fagment 和activity 要用到对象就不得不使用Dagger依赖注入实例。
public class FrombulationActivity extends Activity {@Inject Frombulator frombulator;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// DO THIS FIRST. Otherwise frombulator might be null!((SomeApplicationBaseType) getContext().getApplicationContext()).getApplicationComponent().newActivityComponentBuilder().activity(this).build().inject(this);// ... now you can write the exciting code}
}
如果每新建一个Activity 或者fragment 都要写一次,谁都想吐.
还有专业的原因:是它打破了依赖注入的核心原则:一个类不应该知道如何实现依赖注入。
对我来说这个扩展库就是解决这个问题的。就是要达到注入一次,其他地方就不用理。
添加扩展库
compile 'com.google.dagger:dagger-android-support:2.12'annotationProcessor 'com.google.dagger:dagger-android-processor:2.12'
我们抛弃上面所写的 子Component(ActivityComponent2) 采用新的方式
新建ActivityBindingModule 管理所有的Activity
@Module
public interface ActivityBindingModule {//Di2Activity3 需要的特定 module 可以在这里添加@ContributesAndroidInjector(modules = DiModule.class)Di2Activity3 di3ActivityInjector();@ContributesAndroidInjectorDi2Activity4 di4ActivityInjector();//...省略
}
DiModule 提供一个业务类
@Module
public class DiModule {@Provides@ReusableDouBanService provideUserservice(Retrofit r){return new DouBanService(r);}}
public class DouBanService {private Retrofit mRetrofit;public DouBanService(Retrofit mRetrofit) {this.mRetrofit = mRetrofit;}public void request() {DouBanApi douBanApi = mRetrofit.create(DouBanApi.class);douBanApi.getBook().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Book>() {@Overridepublic void accept(Book book) throws Exception {Log.w("DouBanService", book.toString());}});}}
修改 component
@Component(modules = {AppModule2.class,NetModule2.class,ActivityBindingModule.class,AndroidSupportInjectionModule.class
})
public interface AppComponent2 extends AndroidInjector<MyApplication2> {@Component.Builderinterface Builder {// Module所需要的参数可以这样提供@BindsInstanceBuilder application(Application application);@BindsInstanceBuilder baseUrl(String baseUrl);AppComponent2 build();}//gsonGson gson();Application application();OkHttpClient okHttpClient();SharedPreferences sharedPreferences();Retrofit retrofit();void inject(MyApplication application);
}
MyApplication2
public class MyApplication2 extends Application implements HasActivityInjector {@InjectDispatchingAndroidInjector<Activity> dispatchingActivityInjector;@Overridepublic void onCreate() {super.onCreate();DaggerAppComponent2.builder().baseUrl("https://api.douban.com/").application(this).build().inject(this);}@Overridepublic AndroidInjector<Activity> activityInjector() {return dispatchingActivityInjector;}
}
最后新建一个BaseActivity
public abstract class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {//统一注入,要在super之前。AndroidInjection.inject(this);super.onCreate(savedInstanceState);setContentView(layout());init();}protected abstract void init();@LayoutResprotected abstract int layout();
}
然后让Activity继承BaseActivity.直接使用即可
public class Di2Activity3 extends BaseActivity {@InjectRetrofit mRetrofit;@InjectDouBanService mDouBanService;@Overrideprotected void init() {Log.w("Di2Activity2",mRetrofit.toString());findViewById(R.id.tv_text2).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(Di2Activity3.this,Di2Activity4.class));}});mDouBanService.request();}@Overrideprotected int layout() {return R.layout.activity_main;}
}
结果
fragment中怎么使用 和 源码就不分析了。可以参考下,下面几位大兄弟的文章
Dagger 2应用于Android的完美扩展库-dagger.android
告别Dagger2模板代码:DaggerAndroid原理解析
顺便可以参考一下googlesamples中,dagger的使用实战。
googlesamples todo-mvp-dagger
其他注解
@Qualifier和@Named
这两个注解都是同一个意思。就是当你的module提供了同一个对象。然而在使用的时候dagger2不知道用那个。
限定符为依赖分别打上标记,指定提供某个依赖
@Named
@Module
public class UserModule {@Provides@Singleton@Named("Book1")Book provideBook1() {Book book = new Book();book.setTitle("语文");return book;}@Provides@SingletonBook provideBook2() {Book book = new Book();book.setTitle("数学");return book;}
}
比如我要上面语文的对象
activity
@Inject@Named("Book1")Book mBook;
在module中比如要语文的对象
@Provides@SingletonString provideBook(@Named("Book1")Book book) {return book.getTitle();}
@Qualifier
和上面的一个Scope一个鸟样。自定义@Qualifier
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface BookQualifier {}
然后module
@Provides@Singleton@BookQualifierBook provideBook2() {Book book = new Book();book.setTitle("数学");return book;}
使用
activity
@Inject@BookQualifierBook mBook2;
module
@Provides@SingletonString provideBook(@BookQualifier Book book) {return book.getTitle();}
完成
Lazy (延迟注入)
就是想在使用时再完成初始化,加快速度。
activity
@InjectLazy<Gson> mGson3;//在想要使用的地方
Gson gson = lazyCar.get();
只有在调用 Lazy 的 get() 方法时才会初始化依赖实例注入依赖。
SubComponent
SubComponent被称为是子component,和上面的Component dependencies 有异曲同工之处。
而我们在上面说道。如果另一个Component要复用父component中的对象。
其父Component就要通过方法暴露出来。
而subComponent 就不需要。
我们修改下上面的例子
AppComponentSub
@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface AppComponentSub {/*//gson//子Component 继承关系中不用显式地提供暴露依赖实例的接口Gson gson();Application application();OkHttpClient okHttpClient();SharedPreferences sharedPreferences();Retrofit retrofit();*///声明子Component是谁,表明 ActivityComponentSub 继承 AppComponentSubActivityComponentSub activityComponentSub();void inject(MyApplication application);
}
ActivityComponentSub
@ActivityScope
@Subcomponent(modules = {AModule.class})
public interface ActivityComponentSub {void inject(AMainActivity aMainActivity);
}
MyApplication 构建并提供 AppComponentSub
public class MyApplication extends Application {//子SubComponent继承方式private AppComponentSub mAppComponentSub;@Overridepublic void onCreate() {super.onCreate();
mAppComponentSub = DaggerAppComponentSub.builder().appModule(new AppModule(this)).netModule(new NetModule("https://api.douban.com/")).build();}
}
public AppComponentSub getAppComponentSub() {return mAppComponentSub;}
使用
AMainActivity
@InjectUserService mUserService;MyApplication myApplication = (MyApplication)getApplication();myApplication.getAppComponentSub().activityComponentSub().inject(this);Log.w("AMainActivity", mUserService.toString());
可以看下这大兄弟的详情文章。说的很详细
Dagger 2 完全解析(三),Component 的组织关系与 SubComponent
总结
如果能看到这里的都是真爱
还是那句话。取其精华,去其糟粕
Dagger2demo
这篇关于Dagger2的入坑指南[捂脸][详]!!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!