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

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。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值