上篇簡單介紹了一下依賴注入以及為什么我們要用依賴注入.
這篇主要介紹一下Dagger2的使用方法 并分析一下Dagger2的源碼看看它是怎么實現的。
Dagger2用法還是蠻簡單的,首先我們在Project根目錄的gradle中添加apt依賴
//添加apt依賴
classpath'com.neenbedankt.gradle.plugins:android-apt:1.8'
在我們的Module app gradle里添加apt插件
//添加如下代碼,應用apt插件
applyplugin:'com.neenbedankt.android-apt'
然后添加dagger2依賴以及注解依賴
compile'com.google.dagger:dagger:2.4'
apt'com.google.dagger:dagger-compiler:2.4'
//java注解
compile'org.glassfish:javax.annotation:10.0-b28'
好了喝杯咖啡等待我們gradle構建完畢吧. 所有依賴添加完后我們就可以使用了.
這里我們以一個MVP小例子舉例,先介紹Dagger2的第一種用法
我們傳統的MVP寫法基本似這樣子滴
這是我們創建的Activity v層:
public class MainActivity extends AppCompatActivity implements BaseView{
DemoPresenter mDemoPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@Override
public voidsetXxx() {
}
}
我們創建一個Presenter:
public class DemoPresenter {
private BaseView mBaseView;
private DemoModule mDemoModule;
public DemoPresenter(BaseView baseView) {
mBaseView= baseView;
mDemoModule=newDemoModule();
}
public void getPerson() {
Person person =mDemoModule.getPerson();
if(person.mMsg.equals("1")) {
mBaseView.setXxx();
}
}
}
然后創建一個Module :
public class DemoModule {
publicPersongetPerson(){
Person p=null;
try{
Thread.sleep(1000);
p=newPerson("wubo","11");
}catch(InterruptedException e) {
e.printStackTrace();
}
return p;
}
}
好了這里我們Module 用Thread睡以下假裝請求接口數據,好傳統我們做法是在Activity的onCreate()中
DemoPresenter demoPresenter =new DemoPresenter(this);
然后在合適的地方調用
demoPresenter.getPerson();
現在有了Dagger2我們就不需要這樣寫了 我們可以在MainActivity presenter成員變量上加上@Inject注解
@Inject
DemoPresenter mDemoPresenter;
然后在presenter的構造上同樣加上@Inject注解
public class DemoPresenter {
private BaseView mBaseView;
private DemoModule mDemoModule;
@Inject
public DemoPresenter(BaseView baseView) {
mDemoModule=newDemoModule();
}
public void getPerson() {
Person person =mDemoModule.getPerson();
if(person.mMsg.equals("1")) {
mBaseView.setXxx();
}
}
}
當我們在MainActivity用@Inject標注后Dagger會去標注的這個類的構造上尋找是否同樣有@Inject標注如果有的話生成這個對象,當然如果構造上面你沒有加@Inject那么是不會生成對象的請看官網文檔說明
If your class has @Inject-annotated fields but no @Inject-annotated constructor, Dagger will inject those fields if requested, but will not create new instances. Add a no-argument constructor with the @Inject annotation to indicate that Dagger may create instances as well.
好了現在注解加了對象也生成了,可是怎么把生成對象添加到我們依賴的MainActivity中呢?這就要用到Component,Component是一個橋梁它連接我們的宿主和依賴
我們新創建一個Compnoent接口,注意Component是不需要我們自己去實現的我們只需要去定義接口和實現方法,具體實現細節Dagger會自動幫我們生成是不是灰常貼心。
@Component (modules = {Module.class})
public interface Compnoent {
void inject(MainActivity mainActivity);
}
(modules = {Module.class})
這里面我們要說明一下這個Component需要依賴哪些Module我們可以指定多個這里我們指定Module
貼上Module代碼
@dagger.Module
public class Module {
private BaseView mBaseView;
public Module(BaseView baseView){
mBaseView = baseView;
}
@Provides
public BaseView getBaseView(){
return mBaseView;
}
}
這里我創建了一個Module構造里面參數傳遞宿主類也就是我們的MainActivity至于為什么這么繼續看,下面定義了一個方法使用了
@Provides 咦這是什么東東,這個就是我們提供依賴對象的,比如
說我們可以new出來的對象可以用@Inject去注解構造,那么無法new
出來的對象怎么使用@Inject呢,比如
Interfaces can’t be constructed.
Third-party classes can’t be annotated.
Configurable objects must be configured!
所以Dagger給我們提供了Provides , Provides 是這樣的在Dagger幫我們去創建依賴對象時,依賴對象中存在依賴對象或者構造中存在參數的時候,Dagger是沒有這么智能也幫我們自動去生成的,這個時候Dagger會去@Module 類中 @Provides 依賴的方法找 哪個方法返回值復核依賴那么就賦值給這個依賴。
好了所以需要添加的代碼我們添加完畢,現在我們在需要依賴的地方(比如MainActivity中的onCreate()中)調用
//方法一
DaggerCompnoent.builder().module(new Module(this)).build().inject(this);
就可以使用mDemoPresenter了
接下來我們介紹第二種依賴方式:
第二種方法我們不需要去使用@Inject注解了,其實我個人認為第二種方法不是依賴注入了因為這種方式生成的對象并不是Dagger注入進去的而是我們自己生成的只不過不是在宿主中生成了,可能有點繞我們繼續看下去就會清除了。
第二種方式我們把所有使用@Inject全部去掉, 同樣的還需要創建Module和Compnoent,Module創建的代碼跟方式跟上面的一模一樣,Compnoent 需要我們改一改
//之前我們是這樣創建的
@Component (modules = {Module.class})
public interface Compnoent {
void inject(MainActivity mainActivity);
}
//現在我們改成這樣不需要傳遞宿主類了
@Component (modules = {Module.class})
public interface Compnoent {
DemoPresenter getPresenter();
}
我們看到上面我們把代碼改成了返回一個DemoPresenter 的方法,為什么要這么做呢,因為Dagger會幫我們去實現Component 注解的所有方法,當Dagger實現getPresenter()方法需要返回一個DemoPresenter 時候它怎么辦呢?我們前面說了所有依賴中需要的依賴Dagger都會去Module中的Provide去找,所以我們前面的Module中同樣需要改動的,我們添加一個
拿到DemoPresenter 的方法,你不添加Dagger怎么找的到呢,
@dagger.Module
public class Module {
private BaseView mBaseView;
public Module(BaseView baseView){
mBaseView = baseView;
}
@Provide
public DemoPresenter getPresenter(){
return new DemoPresenter (mBaseView );
}
}
現在我們可以在MainActivity中這么調
//方法二
DemoPresenter mDemoPresenter =DaggerCompnoent.builder().module(new Module(this)).build().getPresenter();
這樣我們就直接生成了一個DemoPresenter 對象
我們總結一下二種方式的區別
方法一: 通過在宿主類(MainActivity)中的依賴上添加@Inject,然后在依賴類的構造上@Inject ,Dagger自動生成依賴類的對象,然后創建一個@Module依賴的Module類,通過Module的構造方法傳入宿主類,聲明成員變量,然后添加一個@Provide依賴的方法,方法返回宿主對象也就是我們聲明的成員變量.最后我們創建一個@Component依賴的Component接口Component 要申明我們要依賴的Module (modules = {Module.class})
Component接口中申明一個方法,方法中參數傳遞我們的宿主對象, void inject(MainActivity mainActivity);
然后在宿主類中調用
DaggerCompnoent.builder().module(new Module(this)).build().inject(this);
方法二:
創建一個@Module依賴的Module類,通過Module的構造方法傳入宿主類,聲明成員變量,然后添加一個@Provide依賴的方法,方法返回宿主對象也就是我們聲明的成員變量,再多添加一個@Provide
Dagger還提供了@Signal
@Provide
public DemoPresenter getPresenter(){
return new DemoPresenter (mBaseView );
}
然后Component接口改成這樣
@Component (modules = {Module.class})
public interface Compnoent {
DemoPresenter getPresenter();
}
宿主類中我們這樣直接生成依賴對象
//方法二
DemoPresenter mDemoPresenter =DaggerCompnoent.builder().module(new Module(this)).build().getPresenter();
二種方式已經介紹完畢,艾瑪,寫的累死寶寶了,好了,使用方法介紹完畢,現在我們解開Dagger神秘的面紗看看Dagger是怎么自動生成代碼的是怎么把依賴注入到宿主類中的,敬請期待你所看到最輕松的Dagger2講解(源碼分析)