一般来说,在mvp开发模式中,会用到依赖注入框架dagger2。
之前接触最多的依赖注入是ButterKnife,它只专注于View的注入,所以有些人觉得不是严格意义上的依赖注入。但其实可以理解为:ButterKnife是Dagger2的补充,Dagger可以注入任何对象,但是在View注入上很麻烦,所以这才有了ButterKnife的产生。
下面先来了解Dagger2的注解
1.@Inject
这个注解有两个作用:
一是在目标类中标记成员变量告诉Dagger这个类型的变量需要一个实例对象。
二是标记类中的构造方法,告诉Dagger,我可以提供这种类型的依赖实例。、
2.@Provide
对方法进行注解,都是有返回值类型的。用来告诉Dagger我们想如何创建并提供该类型的依赖实例。
3.@Module
这个注解用来标记类,这样Dagger就会知道在哪里找到依赖来满足创建类的实例。
4.@Component
注入器,是@Inject 和 @Module 之间的桥梁,把二者组合在一起。这个注解用来标记接口 或者 抽象类。
5.@Scope
作用域。Dagger2通过自定义注解来限定作用域,这样所有的对象都不再需要知道怎么管理自己的实例。默认的作用域注解@Singleton,通常在Android中用来标记在App整个生命周期内存活的实例。也可以自定义一个@PreActivity注解,用来表明生命周期与Activity一致;自定义一个@PreFragment注解,表明生命周期与Fragment一致。
6.@Qualifier
限定符。当一个类的类型不足以标识一个依赖时,可使用这个注解。
7.@SubComponent
如果我们需要父组件全部的提供对象,这时我们可以用包含方式而不是依赖方式,相比于依赖方式,包含方式不需要父组件显式显露对象,就可以拿到父组件全部对象。且SubComponent只需要在父Component接口中声明即可。
接下来看看如何使用
前提
在项目的build.gradle中
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
然后在app的build.gradle中
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
...
compile 'com.google.dagger:dagger:2.2'
apt 'com.google.dagger:dagger-compiler:2.2'
...
}
一、简单使用
最简单的Dagger2使用就只需要两个注解@Inject 和 @Component即可。因为@Inject本身自带两个作用。
如一个User类:
public class User {
public String name; //用这个@Inject表示来表示我可以提供User类型的依赖
@Inject
public User() {
name = "seven";
}
public String getName() {
return name;
}
}
在需要依赖的的目标类中标记成员变量,在这里我们这个目标类是TestActivity。
@Inject //在目标类中@Inject标记 表示 我需要这个类型的依赖实例
User mUser;
在Component中
/**
* 没有module 和 dependencies 的情况下,纯粹用@Inject来提供依赖
*/
@Component()
public interface TestComponent{
/**
* 这里的TestActivity是目标类,让Component知道需要往哪个类中注入
这个方法名可以是其他的,但是推荐使用inject
目标类必须精确,不能使用其父类。
*/
void inject(TestActivity activity);
}
然后Make Project(Ctrl+F9)就会在build文件夹内生成对应的代码。
TestComponent接口会生成一个以Dagger为前缀的DaggerTestComponent类。
使用这个类就可以完成依赖对象的注入。
DaggerTestComponent.builder().build().inject(this);
二、采用@Module提供依赖
实例在Module中实例化。
@Module
public class TestModule{
@Provides
public User provideUser(){
return new User();//实例化
}
}
然后在Component中依赖Module
@Component(modules = TestModule.class)
public interface TestComponent(){
void inject(TestActivity activity);
}
目标类TestActivity中
@Inject //表示这里需要这个类型的实例
User mUser;
做完以上编码,编译之后就可以在目标类中进行依赖注入了:
DaggerTestComponent.builder()
.testModule(new TestModule())
.build()
.inject(this);
这样,依赖注入完成之后,mUser已经被赋值了。
三、@Module 和 @Inject 优先级问题
如果同时有@Module 和 @Inject构造方法 来提供同一类型的实例,Dagger2会调用@Module提供的依赖实例。也就是@MOdule级别高点。
四、组织Component
三种方式:
1》依赖方式
一个Component可以依赖一个或者多个Component,采用的是@Component的dependencies属性。
2》包含方式
这里就用到了@SubComponent注解,用这个注解标记接口或者抽象类,表示它可以被包含。一个Component可以包含一个或者多个Component,而且被包含的Component还可以继续包含其他的Component。
3》继承方式
注意几点:
1.> Component的作用域 必须跟 对应的Module作用域一致。如果@Module没有标记作用域,那就不影响。
2.> Component 和 依赖的Component作用域范围不能一样,否则会报错。一般来讲,我们应该对每个Component都定义不同的作用域。
3. >@Singleton并不是真的能创建单例,但是我们依然可以保证在App的生命周期内一个类只存在一个对象。@Singleton更重要的作用是通过标记来提醒我们自己来达到更好的管理实例的目的。
项目中一般使用方式是:
ApplicationModule.java
@Module
public class ApplicationModule {
//实例已在AndroidApplication 中初始化
private final AndroidApplication mApplication;
private final DaoSession mDaoSession;
private final RxBus mRxBus;
public ApplicationModule(AndroidApplication application, DaoSession daoSession, RxBus rxBus) {
mApplication = application;
mDaoSession = daoSession;
mRxBus = rxBus;
}
@Provides
@Singleton
Context provideApplicationContext() {
return mApplication.getApplication();
}
@Provides
@Singleton
RxBus provideRxBus() {
return mRxBus;
}
@Provides
@Singleton
DaoSession provideDaoSession() {
return mDaoSession;
}
}
ApplicationComponent.java
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent{
Context getContext();
RxBus getRxBus();
DaoSession getDaoSession();
}
AndroidApplication .java
public class AndroidApplication extends Application {
private ApplicationComponent appComponent;
@Override
public void onCreate() {
super.onCreate();
setDaggerConfig();
}
private void setDaggerConfig() {
// 这里不做注入操作,只提供一些全局单例数据
appComponent = DaggerSevenAppComponent.builder().applicationModule
(new ApplicationModule(this, mDaoSession, mRxBus)).build();//
}
/**
* 静态调用
* @return
*/
public static ApplicationComponent getAppComponent() {
return appComponent ;
}
}
然后在使用的时候
ChannelModule.java
@Module
public class ChannelModule {
private ChannelActivity mView;
public ChannelModule(ChannelActivity view){
this.mView = view;
}
@Provides
public BaseQuickAdapter provideManageAdapter(){
return new ManageAdapter(mView);
}
@PreActivity
@Provides
public IChannelPresenter provideManagePresenter(DaoSession daoSession, RxBus rxBus){
return new ChannelPresenter(mView, daoSession.getNewsTypeInfoDao(), rxBus);//父类BaseActivity中需要Presenter
}
}
ManageComponent.java
@PreActivity
@Component(dependencies = ApplicationComponent.class, modules = ChannelModule.class)
public interface ManageComponent {
void inject(ChannelActivity activity);
}
其中
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PreActivity {//自定义注解,表明生命周期跟Activity一致
}
在ChannelActivity中
public class ChannelActivity extends BaseActivity<IChannelPresenter> implements IChannelView{
...
@Inject
BaseQuickAdapter mCheckedAdapter;
@Override
protected void initInjector() {
DaggerManageComponent.builder()
.applicationComponent(AndroidApplication.getAppComponent())
.channelModule(new ChannelModule(this))
.build()
.inject(this);
}
...
}
暂时就到记录上面这些,后续再补充完善。。。