Dagger2使用进阶

来源:互联网 发布:apache 安装 编辑:程序博客网 时间:2024/04/27 01:39

上一篇介绍了Dagger2简单的使用,这次我们接着介绍稍微复杂一点的使用场景。

module的provide方法带参数

首先我需要注入一个书名,代码如下:

public class MainActivity extends AppCompatActivity {    @Inject    String bookName;}

然后我们接着编写module的代码

@Modulepublic class ActivityModule {    @Provides    String provideName(BookBean book){        return book.getTitle();    }    @Provides    BookBean provideBook(){        BookBean bookBean = new BookBean();        bookBean.setTitle("c++从入门到放弃");        return bookBean;    }    @Provides    PeopleBean providePeople(){        People peopleBean = new PeopleBean();        peopleBean.setTitle("mike");        return peopleBean;    }}

我们可以看到provideName(BookBean book)方法是需要有一个BookBean的参数,当我们需要注入书名时,是通过传入的BookBean获取的。那这个BookBean怎么来的呢?大家可能已经注意到了下面还有一个provideBook()方法的返回类型是BookBean。没错,Dagger会自动寻找返回值为BookBean的方法,并将其返回的参数传入到provideName(BookBean book)方法中。这就是为什么不是调用providePeople()方法了,因为返回值不匹配。但是必须有一个条件,就是provideBook()必须被@Provides注解

@Qualifier注解

说到这里,那么问题来了,如果我的两个方法返回值一样的情况下怎么办呢?看代码:

@Modulepublic class ActivityModule {    @Provides    String provideName(BookBean book){        return book.getTitle();    }    @Provides    BookBean provideBook(){        BookBean bookBean = new BookBean();        bookBean.setTitle("c++从入门到放弃");        return bookBean;    }    @Provides    BookBean provideBook2(){        BookBean bookBean = new BookBean();        bookBean.setTitle("android从入门到放弃");        return bookBean;    }}

这里就要介绍一个新的注解了@Qualifier。
首先我们先自定义两个注解,并用@Qualifier修饰

@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface Android {}
@Qualifier@Retention(RetentionPolicy.RUNTIME)public @interface Cpp {}

然后修改module代码

    @Provides    @Singleton    @Cpp    BookBean provideBook() {        BookBean bookBean = new BookBean();        bookBean.setTitle("c++从入门到放弃");        return bookBean;    }    @Provides    @Singleton    @Android    BookBean provideBook2() {        BookBean bookBean = new BookBean();        bookBean.setTitle("Android从入门到放弃");        return bookBean;    }

可以看到,只是添加了刚才自定义的注解。这就相当于给他们取了一个别名。
最后修改module的provideName

  @Provides    String provideName(@Android BookBean book){        return book.getTitle();    }

注意看,参数前面增加了一个@Android注解。
至此,@Qualifier的用法就介绍完了。值得注意的是接下来讲的Component依赖有一点不同,会在下文介绍。


Component添加依赖

Component依赖就是指一个Component依赖另一个,有点类似于java的继承。
首先,我们先来写要被依赖的Component
这个例子里,我们模拟网络请求。所以需要依赖注入一个Retrofit,同时要使注入的Retrofit的生命周期和app保持一致,还好是一个单例。这时候我们要使用到两个新的注解@Singleton、@Scope。
先看MainActivity的代码

public class MainActivity extends AppCompatActivity {    @Inject    Retrofit retrofit;    @Inject    String bookName;    ...}

这里我们就是向服务器请求数据并打印出来。还有就是把注入的书名显示在textview上,这个主要作用后面再说。
接下来看被依赖的Component和Module的代码:

@Modulepublic class AppModule {    private Retrofit retrofit;    @Provides    @Singleton    OkHttpClient provideOkHttpClient() {        return new OkHttpClient.Builder().build();    }    @Provides    @Singleton    Retrofit provideRetrofit(OkHttpClient okHttpClient) {        return retrofit = new Retrofit.Builder()                .client(okHttpClient)                .baseUrl("http://api.douban.com/")                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .build();    }    // 演示@Qualifier在Component依赖时的使用    @Provides    @Singleton    @Cpp    BookBean provideBook() {        BookBean bookBean = new BookBean();        bookBean.setTitle("c++从入门到放弃");        return bookBean;    }    @Provides    @Singleton    @Android    BookBean provideBook2() {        BookBean bookBean = new BookBean();        bookBean.setTitle("Android从入门到放弃");        return bookBean;    }}
@Singleton@Component(modules = AppModule.class)public interface AppComponent {    OkHttpClient getClient();    Retrofit getRetrofit();    @Android    BookBean getBook();}

module中有三个参数的生成,都是单例。然后在Component中提供方法将module中的生成暴露给子图(这正是Dagger中 components工作的重要性质:如果你不想把modules的类型暴露出来,那么你就只能显示地使用它们。在这个例子中,我把这些元素暴露给子图, 如果你把他们删掉,编译的时候就会报错。这里不理解就先记着要这么写就行了)。
(BookBean getBook();被@Android修饰了,这就是前面提到的有所不同的就是如果你给方法取了别名,这里暴露的方法也需要被相同的注解修饰。)

然后来写真正的Component:

@ActivityScope@Component(modules = ActivityModule.class, dependencies = AppComponent.class)public interface ActivityComponent {    void inject(MainActivity mainActivity);}

这里多了一个@ActivityScope注解,这是一个我自定义的注解,看代码:

@Scopepublic @interface ActivityScope {}

它的作用是为了注入的Retrofit和app的生命周期保持一致,与Component的依赖无关。(至于@Scope我也没理解)
这里看到多加了一条dependencies = AppComponent.class,这就是将需要依赖的Component添加进去。
module的代码:

@Modulepublic class ActivityModule {    @Provides    String provideName(@Android BookBean book){        return book.getTitle();    }}

然后module就没什么变化了,但是这里我加了provideName(BookBean book)方法。这是给MainActivity中的String bookName生成注入。而provideName(BookBean book)中的BookBean则来自AppModule中的BookBean provideBook()方法返回的值。也就是说带参的provide方法不一定要在同一个module中,也可以在被依赖的module中。
最后,在MainActivity中使用

public class MainActivity extends AppCompatActivity {    @Inject    Retrofit retrofit;    @Inject    String bookName;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        inject();        Github github = retrofit.create(Github.class);        github.htmls("1220562")                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Action1<BookBean>() {                    @Override                    public void call(BookBean bookBean) {                        System.out.println(bookBean);                    }                });        TextView tv = (TextView) findViewById(R.id.textview);        tv.setText(bookName);    }    private void inject() {        DaggerActivityComponent.builder()                .appComponent(DaggerAppComponent.create())                .activityModule(new ActivityModule())                .build().inject(this);    }}

主要看inject()方法的代码,可以看到我们先生成了一个DaggerActivityComponent.builder()然后调用了appComponent()方法,此时传入的就是要依赖的Component,这里就是DaggerAppComponent.create(),其他的就和以前一样了。

参考文章:http://www.jianshu.com/p/05ad9ad8a3e8
https://dreamerhome.github.io/2016/07/11/dagger%20for%20code/

1 0
原创粉丝点击