您的位置:首页 > 移动开发 > Android开发

Android之dagger2的简单运用和详细解读(入门)

2016-09-14 23:46 519 查看

dagger2的使用和理解

dagger2的使用,给程序带来了非常好的解耦,废话不多说,直接开始

基本的配置:

在project根目录build.gradle添加

dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}


在module 的build.gradle添加

apply plugin: 'com.neenbedankt.android-apt'
dependencies { ...
compile 'com.google.dagger:dagger:2.0'
apt 'com.google.dagger:dagger-compiler:2.0'
compile 'org.glassfish:javax.annotation:10.0-b28' // Java标注
}


注意:

1.使用@Inject时,不能用private修饰符修饰类的成员属性。

2.项目中同时用了Butterknife,需要在module build.gradle添加

packagingOptions { exclude 'META-INF/services/javax.annotation.processing.Processor' }


3.使用@Scope注解的Component不能被没有使用其注解的Component所依赖。

一:dagger2在android中依赖注入代码实现

这是我之前一个项目关于dagger2的相关代码,具体里面的内容不用管,我们只需要关注每个@provides方法的传入参数以及返回结果就可以。每一行代码都注释得很清楚,相信大家读完,基本的流程也就明白了。

1.建立接口component,表示连接器,并且用注解Component标记,如果有Module,可以在引入。(Component是连接@Module和@Inject的桥梁)

@Singleton @Component(modules = {ApplicationMoudle.class, ApiMoudle.class})
public interface ApplicationComponent {
Context getContext();//对外暴露Context ,这个context由ApplicationMoudle提供
//对外暴露OkHttpHelper,这个context由ApplicationMoudle提供
OkHttpHelper getOkHttpHelper();
//对外暴露UserStorage ,这个context由ApplicationMoudle提供
UserStorage getUserStorage();
//对外暴露UserApi ,这个context由ApiMoudle提供
UserApi getUserApi();
//对外暴露TicketApi ,这个context由ApiMoudle提供
TicketApi getTicketApi();
//要注入到MyApplication
void inject(MyApplication application);
}


2.创建类module一个或多个,并且用注解@Module标记。

@Provides 表示对外提供

@Singleton 表示单例,对象只会被初始化一次,之后的每次都会被直接注入相同的对象

@Named 表示

@Module
public class ApplicationMoudle {
private Context context;
//构造方法会在创建component的时候,手动去new创建,并且传入context,和普通对象是一模一样的
public ApplicationMoudle(Context context){
this.context = context;
}
//向外提供Context
@Provides @Singleton
public Context provideApplicationContext(){
return context;
}
//向外提供OkHttpClient ,并且用@Named(“api”)做标记,因为这个Module里面有两个提供OkHttpClient 的方法,需要区分。
@Provides @Singleton @Named("api")
OkHttpClient provideApiOkHttpClient(){
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS);
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(loggingInterceptor);
return builder.build();
}
//向外提供OkHttpClient ,这个参数OkHttpClient 从上一个标记了@Named("api") 方法提供而来。
@Provides @Singleton
OkHttpClient provideOkHttpClient(@Named("api") OkHttpClient mOkHttpClient) {
OkHttpClient.Builder builder = mOkHttpClient.newBuilder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.retryOnConnectionFailure(true);
builder.interceptors().clear();
return builder.build();
}
//向外提供LayoutInflater
@Provides @Singleton
LayoutInflater provideLayoutInflater(Context context) {
return (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
//向外提供UserStorage
@Provides @Singleton
UserStorage proviceUserStorage(Context mContext){
return new UserStorage(mContext);
}
//向外提供RequestHelper,参数UserStorage 由proviceUserStorage方法提供而来。
@Provides @Singleton
RequestHelper proviceRequestHelper(Context mContext,UserStorage mUserStorage){
return new RequestHelper(mContext,mUserStorage);
}
//向外提供OkHttpHelper ,参数OkHttpClient 由provideOkHttpClient()方法提供而来。
@Provides @Singleton
OkHttpHelper provideOkHttpHelper(OkHttpClient mOkHttpClient) {
return new OkHttpHelper(mOkHttpClient);
}
}

@Module
public class ApiMoudle {
//向外提供UserApi ,参数OkHttpClient 由ApplicationModule的提供方法provideOkHttpClient()提供而来。
@Provides @Singleton
public UserApi proviceUserApi(@Named("api") OkHttpClient okHttpClient){
return new UserApi(okHttpClient);
}
//向外提供TicketApi ,参数OkHttpClient 由ApplicationModule的提供方法provideOkHttpClient()提供而来。
@Provides @Singleton
public TicketApi proviceTicketApi(@Named("api") OkHttpClient okHttpClient){
return new TicketApi(okHttpClient);
}
}


可以发现,每一个提供出去的对象,又可以为其他的提供方法提供参数,也为@inject标注的构造函数提供参数。

总而言之:

如果@Provides方法有参数,这个参数需要通过其他的@Provides方法或者@Inject注解的构造方法获得。

3.建立普通类,我们需要注入的类。在构造函数上方通过@Inject注解标记。

public class MainPresenter  {
private Context context;
@Inject
public MainPresenter(Context context){//
this.context = context;
}
}


4.在Application里面的使用

public class MyApplication extends Application {
private ApplicationComponent mApplicationComponent;
@Inject MainPresenter  mMainPresenter ;//
@Override
public void onCreate() {
super.onCreate();
initComponent();
}

private void initComponent() {
mApplicationComponent =
DaggerApplicationComponent.builder()
.applicationMoudle(new ApplicationMoudle(this))
.apiMoudle(new ApiMoudle())
.build();
mApplicationComponent.inject(this);//这样,就会把所有@Inject标记的对象进行注入操作
}
}


dagger2的调用步骤:

1.创建DaggerApplicationComponent对象,创建需要Component依赖的Module对象(在程序中手动new创建)。

2.调用inject()注入。

dagger2的工作方式:

可以看到@Inject MainPresenter mMainPresenter 一句话就实现了注入(创建对象)。

我们可以看到MainPresenter的构造函数有一个@Inject注解

@Inject

public MainPresenter(Context context){

this.context = context;

}

1.对于@Inject标记的MainPresenter对象,dagger2首先会去到MainPresenter去找构造函数。如果该构造函数恰好也被@Inject标记,那么就会调用这个方法会new出对象,但是这里的构造函数需要一个参数context,而ApplicationModule有一个提供context的方法,所以context由ApplicationModule可以得到提供。那么,创建对象,就顺利完成了。

如果该构造函数没有被@Inject标记,那么就直接去Module里面去寻找对应的提供MainPresenter的方法,从而实现实例化创建对象。

那么,其实我们根本不需要Module,一样可以实现注入,使用构造器注入即可。

使用构造器注入具有局限性:

1.不能给这个类中的多个构造器作@Inject注解。

2.第三方类,系统类,我们就无法在他构造方法前面加@inject。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: