dagger2的配置及基本使用(一)

来源:互联网 发布:封印者画质优化 编辑:程序博客网 时间:2024/05/17 16:44

一、配置:

1.1 在Project的gradle脚本中配置

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

1.2在Module的gradle脚本中配置

apply plugin: 'com.neenbedankt.android-apt'dependencies {apt 'com.google.dagger:dagger-compiler:2.11'    compile 'com.google.dagger:dagger:2.11'    }

二、代码实现

2.1、使用@Inject和@Component实现依赖注入

2.1.1: 在实体类的构造方法中标注@Injecct,表示其提供依赖,代码如下:

package testdagger.com.xn.testdagger2.modle;import android.util.Log;import javax.inject.Inject;/** * Created by  贺谋昌 on 2017/8/1. */public class Watch {    @Inject    public Watch() {    }    public void work() {        Log.e("Watch", "Dagger2 watch is work");    }}

2.1.2:创建注入器,即提供依赖和目标类之前的桥梁,是一个用@Conponent标注的接口

代码如下:

package testdagger.com.xn.testdagger2.component;import dagger.Component;import testdagger.com.xn.testdagger2.MainActivity;/** * Created by  贺谋昌 on 2017/8/1. */@Componentpublic interface MainActivityComponent {    void inject(MainActivity activity);}

其创建的方法中传入的参数为目标类的实体

2.1.3

在目标类中进行注入,并标注依赖注入的实体类

public class MainActivity extends Activity {    @BindView(R.id.btn)    Button btn;    @Inject    Watch watch;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        DaggerMainActivityComponent.create().inject(this);    }    @OnClick(R.id.btn)    public void onViewClicked() {        watch.work();    }}

DaggerMainActivityComponent这个类是在component类完成之后进行reBuild后自动生成的类。

2.2、使用@Module和@Provides提供依赖

如果代码中使用了第三方的类库,那么目标类所需的依赖是无法进行标注的,因为无法更改实体类的源代码,比如一个jar包,这时我们用@Module和@Provides提供依赖。

2.2.1、新建一个标注@Module的类,并通过标注@Provides的方法返回实体类的对象,代码如下:

/** * Created by  贺谋昌 on 2017/8/1. */@Modulepublic class GsonModule {    @Provides    public Gson getGson() {        return new Gson();    }}

2.2.2、使用已经创建的component来管理Module,只要在类名处标注上管理的是哪个Module即可,代码如下:

** * Created by  贺谋昌 on 2017/8/1. */@Component(modules = GsonModule.class)public interface MainActivityComponent {    void inject(MainActivity activity);}

2.2.3、在目标类中注入,并标注要使用的实体类,代码如下:

public class MainActivity extends Activity {    @BindView(R.id.btn)    Button btn;    @Inject    Watch watch;    @Inject    Gson gson;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        DaggerMainActivityComponent.create().inject(this);    }    @OnClick(R.id.btn)    public void onViewClicked() {        watch.work();        JSONObject object = new JSONObject();        try {            object.put("name", "贺贺");            object.put("age", 24);            Man man = gson.fromJson(object.toString(), Man.class);            Log.e("MainActivity", man.getName());        } catch (JSONException e) {            e.printStackTrace();        }    }}

2.3、如果要注入的对象是抽象的则不能用@Inject来提供依赖,这时要用@Module,案例如下:

Engine是一个抽象类

public abstract class Engine {public abstract String work();}

MyEngine是Engine的子类

public class MyEngine extends Engine {    @Override    public String work() {        return "MyEngine is working";    }}

Car持有Engine的对象

public class Car {    Engine engine;   @Inject    public Car(Engine engine) {        this.engine = engine;    }    public String run() {        return engine.work();    }}

2.3.1、在component中提供一个方法,给Engine提供实例

@Modulepublic class GsonModule {    @Provides    public Engine getEngine() {        return new MyEngine();    }}

2.3.2在MainActivity中注入

  @Inject    Car car;    ...  DaggerMainActivityComponent.create().inject(this);    ....  Log.e("MainActivity",  car.run() );

2.4、@Name和Qualifier的基本使用

如果@Inject标注的多个构造或是@Provides标注的方法返回的是同一种类型的值,那么程序就不知道使用哪一个来提供依赖,这时就会报错,我们就可以使用@Qualifier来标注我们要使用的是哪一个,@Name是@Qualifier的一种实现。案例如下:
如果Engine的子类有两个,除了MyEngine之外还有HerEngine,在Module中返回的Engine的实例的方法中,有两个方法,一个返回MyEngine一个返回HerEngine,这时我们就要标注好哪个方法返回哪个实例,并且目标类需要哪个实例,可以用@name(字符串)也可以自定义Qualifier,示例代码如下:

  //首先定义两个自定义的Qualifier  @Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface My {}........@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface Her {}....//在Module中标注好,哪个方法对应的哪个类的实例  @Provides    @My    public Engine getEngine() {        return new MyEngine();    }    @Provides    @Her    public Engine getHerEngine() {        return new HerEngine();    } // 标注好目标类需要哪个实例      public class Car {    Engine engine;    @Inject    public Car(@Her Engine engine) {        this.engine = engine;    }    public String run() {        return engine.work();    }}

使用@Name来标注则更为简单
“`
@Provides
@Named(“My”)
public Engine getEngine() {
return new MyEngine();
}

@Provides@Named("Her")public Engine getHerEngine() {    return new HerEngine();}//在需要依赖的类中同样使用@Name标注好public class Car {Engine engine;@Injectpublic Car(@Named("Her") Engine engine) {    this.engine = engine;}public String run() {    return engine.work();}

}

2.5、Dagger2实现单例模式

2.5.1、实现局部单例

在提供依赖的地方标注@Singleton

   @Singleton    @Provides    public Gson getGson() {        return new Gson();    }

在Module中标注@Singleton

  @Singleton@Component(modules = GsonModule.class)public interface MainActivityComponent {    void inject(MainActivity activity);}

//这样就完成了局部单例

2.5.2、使用@Scope实现全局单例模式

其实@Singleton是被@Scope标注的注解,@Scope标注实际上就是用来实现局部单例的,它的本质就是注解的注解,只要在想要实现某个类是单例模式,只需要在其提供依赖的地方标注被@Scope标注的注解,然后在其component中标注被@Scope标注的注解,上述@Singleton就是做了这样的操作。还有一个要注意的点就是component会每注入一次就实例化一次,所以我们只要让Component成为单例,就可以实现全局单例了。下面开始正式的实现:

新建一个被@Scope标注的注解

   @Scope@Retention(RetentionPolicy.RUNTIME)public @interface ApplicationScope {}
首先在提供依赖处标注刚定义的注解@Modulepublic class GsonModule {    @ApplicationScope    @Provides    public Gson getGson() {        return new Gson();    }然后在提供依赖处和component处标注此注解@ApplicationScope@Component(modules = GsonModule.class)public interface MainActivityComponent {    void inject(MainActivity activity);    void inject(SecondActivity activity);}新建一个Application在onCreate中实例化component,这样就能保证该component只有一个实例public class MyApplication extends Application {    MainActivityComponent component;    @Override    public void onCreate() {        super.onCreate();        component = DaggerMainActivityComponent.create();    }    public static MyApplication get(Context context) {        return (MyApplication) context.getApplicationContext();    }    public MainActivityComponent getComponent() {        return component;    }}在需要使用的地方,用实现单例的component进行注入即可,在这里我们分别在两个不同对的Activity中打印该类实例的HashCode,若是相同,就说明我们成功实现了单例.public class MainActivity extends Activity {    @Inject    Gson gson;    @Inject    Gson gson1;    @BindView(R.id.jump)    Button jump;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);      MyApplication.get(this).getComponent().inject(this);    }    @OnClick({R.id.btn})    public void onViewClicked() {        Log.e("MainActivity", car.run());        Log.e("MainActivity", "gson:" + gson.hashCode() + " gson1" + gson1.hashCode());    }}在另一个Activity中我们做相同的操作public class SecondActivity extends Activity {    @BindView(R.id.secoond_btn)    Button secoondBtn;    @Inject    Gson gson;    @Inject    Gson gson1;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_second);        ButterKnife.bind(this);        MyApplication.get(this).getComponent().inject(this);    }    @OnClick(R.id.secoond_btn)    public void onViewClicked() {        Log.e("SecondActivity", "gson:" + gson.hashCode()+" gson1"+gson1.hashCode());    }}

我的测试结果如下:
E/MainActivity: gson:1111566360 gson11111566360
E/SecondActivity: gson:1111566360 gson11111566360
可以看到四个HashCode都一样,我们的全局单例模式算是实现了。

还有两个注解的使用,@dependencies和subComponent有空再说吧,是用来描述component的组织关系的。

原创粉丝点击