Dagger2学习笔记

(个人学习笔记)

作用:对象的管理,降低程序耦合。

框架类型:Dagger2是一个依赖注入框架。

性能:Dagger2的注解框架采用的是apt代码自动生成技术,注解停留在编译阶段,所以说不影响性能。

主要常用标识:@Inject,@Component,@Module,@Provides,@SubComponent,@SingleTon,modules,dependiences。

*ButterKnife也是一种注解框架,采用的也是apt代码自动生成技术。

看了很多次Dagger2,但是从入门到放弃N多次。下面来总结一下Dagger2的一些用法,现在Dagger2,Annotation,ButterKnife这种注解。

首先我们来看下面这张关系图。这就是Dagger2的使用模式。通过一个@componet这个桥梁,我们大大的提升了程序的解耦性。

假设有6,7个地方需要使用A.class对象。但此时A对象的构造数,增加或减少一个或者N个参数。以往的做法,我们会挨个儿在new了A.class的地方去修改对象。但现在我们只需要修改A.class本身就好了。*不同的情况,改变的位置也不尽相同

 

根据上面这张关系图,来一份无参的案例。(主要是对@Inject,@Componet 注解的使用)

1.A.class类

public class NoParam {
    @Inject
    public NoParam() {
    }
}

2.B.interface

@Component
public interface NoParamComponet {
    //指定要注入的目标NoParamActivity 
    void inject(NoParamActivity noParamActivity);
}

3.C.Activity 值得注意的是:@Inject的对象不可用private修饰,要用public或者protect。

public class NoParamActivity extends Activity {

    @Inject
    protected NoParam noParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_doublewave);
        //触发dagger注入机制
        DaggerNoParamComponet.create().inject(this);
        Toast.makeText(this, "结果="+noParam.hashCode(), Toast.LENGTH_SHORT).show();
    }
}

有参数的案例

1.参数对象一InsiceParam

public class InsideParam {
    @Inject
    public InsideParam() {
    }
}

2.参数对象二HaveParam。包含参数一

public class HaveParam {
    @Inject
    protected InsideParam insideParam;

    public HaveParam(InsideParam insideParam) {
        this.insideParam = insideParam;
    }
}

3.B.interface(Component对象)

@Component
public interface HaveParamComponet {
    void inject(HaveParamActivity haveParamActivity);
}

4.C.activity(调用对象)

public class HaveParamActivity extends Activity {

    @Inject
    protected HaveParam haveParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_dagger_student);
        DaggerHaveParamComponet.create().inject(this);
        Toast.makeText(this,"结果="+haveParam.hashCode()+
                haveParam.insideParam.hashCode(),Toast.LENGTH_LONG).show();
    }
}

这里有一点值得注意,在HaveParam里面的时候,并没有对InsideParam做create().inject()的操作来完成注入。那到底是谁帮我们把InsideParam完成操作了呢?

答案:是HaveParamActivity对InsideParam完成了注入操作。

解释:在HaveParamActivity里面,在进行inject对象HaveParam的时候发现HaveParam的构造函数被inject标注,且带有一个参数,于是Dagger2去寻找InsideParam,它的构造参数被@Inject标注且无参数。于是Dagger2把InsideParam注入给HaveParamActivity。再去实例化的时候用的是已经注入给HaveParamActivity的那个InsideParam实例。

分析结果:HaveParamActivity将InsideParam实例化,将实例化后的InsideParam拿去给HaveParam使用。

调用第三方类库对象

上面是我们自己定义的对象类,那如何调用第三方类库的对象?(主要是@Module,@Provides的使用)

案例如下:

1.HttpModule(这里使用了@Module和@Provides。)

@Module的作用:我们需要注入的类是第三方类库,我们无法再构造函数直接加@Inject注解,还有一个问题就是如果有多个构造函数的问题,Module封装依赖就是为了解决这些问题。

@Provides作用:标注@Module中能够提供实例化的方法。

@Module
public class HttpMudule {

    @Provides
    OkHttpClient providerHttpClient(){
        return new OkHttpClient();
    }
}

2.Component

使用@Component标注这个接口,并使用modules=的方法链接上第一步中编写的Module类(连接HttpMudule类);

@Component(modules = HttpMudule.class)
public interface HttpModuleComponet {
    void inject(HttpActivity httpActivity);
}

3.HttpActivity

public class HttpActivity extends Activity {

    @Inject
    protected HttpMudule httpMudule;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        setContentView(R.layout.layout_doublewave);
        DaggerHttpModuleComponet.create().inject(this);
        Toast.makeText(this, "结果="+httpMudule.hashCode(), Toast.LENGTH_SHORT).show();
    }
}

Module中的@Provides含参,且参数依赖另外的@Provides返回值

先逻辑分析这个过程:

第一步:在Module内寻找,@Provides方法返回值=含有参数的@Provides的参数值。

第二步:如果第一步中没有在Module中找到那个返回值的@Provides方法。则去看这个类的构造函数是否被@Inject标注

由此可得:一般情况下,Module中方法返回值都不能相同。但有办法使其返回值相同。

案例如下:

@Module
public class HttpMudule {

    private int num;

    public HttpMudule(int num) {
        this.num=num;
    }


    @Provides
    OkHttpClient providerHttpClient(int num){
        OkHttpClient okHttpClient=new OkHttpClient();
        okHttpClient.setTimeSize(this.num);
        return okHttpClient;
    }

    @Provides
    RetrofitDemo providerRetrofit(OkHttpClient okHttpClient){
        return new RetrofitDemo(okHttpClient);
    }

}

 HttpActivity的Componet注入则修改为如下写法,动态输入参数num=200。 

public class HttpActivity extends Activity {

    @Inject
    protected HttpMudule httpMudule;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        setContentView(R.layout.layout_doublewave);
        //DaggerHttpModuleComponet.create().inject(this);//之前的写法
        DaggerHttpModuleComponet.builder().httpMudule(new HttpMudule(200)).build().inject(this);//@Module依赖另外的依赖之后的写法(不一定全是这样写)。
        Toast.makeText(this, "结果="+httpMudule.hashCode(), Toast.LENGTH_SHORT).show();
    }
}

Component和Component之间的依赖关系的实现

类和类之间的依赖有extends来实现,component和Component的依赖由DependencesubComponent来实现。

1.dependence

逻辑:A.class  B.class  AComponent(父)  BComponent(子)  AActivity  BActivity

在BComponent中加入dependencies来表明依赖于AComponent。

在AActivity里面增加一个方法,返回结果为AComponent对象的方法getAComponent()。

在BActivity里面注入之前,new一个AComponent,对象=AActivity.getAComponent();

在BActivity注入的时候,用build,可以注入Acommponent。从而使用AComponent的注入,完成依赖。

2.subComponent(wasabi的Part 0...   0...

HttpFragmentComponent是子。HttpActivityComponent是父。

a.在子Component中加入@Subcomponent标识

b.在父Component中获得定义子Component的方法。

c.在子Activity注入的时候,Component实例化。

Scope作用域---单例

a.无Module的使用方式。

@Singleton
public class HttpMudule {
    OkHttpClient providerHttpClient(){
        return new OkHttpClient();
    }
}
@Singleton
@Component
public interface HttpModuleComponet {
    void inject(HttpActivity httpActivity);
}

Actvity和之前的一样。就不po了。

结果分析:@Singleton不可以标注构造器。依赖类标注了@Singleton,那么Component也要标注@Singleton。否则会报错。

b.带module的使用方式。

@Module
public class HttpMudule {
    @Singleton
    @Provides
    OkHttpClient providerHttpClient(){
        return new OkHttpClient();
    }
}
@Singleton
@Component(modules = HttpMudule.class)
public interface HttpModuleComponet {
    void inject(HttpActivity httpActivity);
}

其他和上面一样。

结果分析:@Module内的@Provides需要被标注@Singleton。Component需要被标注上@Singleton

对于@Scope的总结:

在某个范围里它是单例(何为作用域呢,可以看作是我们在程序中实例化的Component的生命周期的长短:如果在Application里build的那它的作用域就是整个App的生命周期,如果是在Acitivity中build的那它的作用域就跟此Acitivity的生命周期相同,依次类推)。

后续补充......

展开阅读全文

没有更多推荐了,返回首页