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/
- Dagger2使用进阶
- Dagger2进阶使用
- Dagger2 进阶
- Android开发进阶——使用Dagger2
- Dagger2基础与进阶
- Dagger2 进阶(二)
- Dagger2 进阶 (三)
- Dagger2 进阶 (四)
- Dagger2 进阶(五)
- Dagger2使用
- Dagger2使用
- Dagger2使用
- Dagger2使用
- Dagger2使用
- Dagger2使用
- Dagger2使用
- Dagger2-android (不是dagger2)使用
- Dagger2使用(一)Dagger2 介绍
- 设计模式-命令模式
- c# int数组 每个int的各个位排序 和数组排序
- 哈理工OJ 1795 发现王国之旅(最小生成树)
- lstm的数学推导
- 蓝牙连接建立
- Dagger2使用进阶
- 读取common.properties文件
- jzoj 4683. 【GDOI2017模拟8.11】矩阵 后缀数组+哈希表
- Android开源库之使用ZXing开源库实现二维码功能
- 爬虫抓取美团网上所有商家信息
- oracle 启动监听提示 :The listener supports no services
- 重建二叉树
- 简单了解字符与字符集
- 测试