dagger2 循序漸進學習(包會)(二)

文章索引
dagger2 循序漸進學習(一)依賴注入基礎知識(包會)
dagger2 循序漸進學習(二)
dagger2 循序漸進學習(三) 實例1,application中的應用

昨天寫了關于dagger2 的重要但比較易于理解的基礎知識 依賴注入,這里是鏈接dagger2 循序漸進學習(一)依賴注入基礎知識
今天這篇就開始主要講dagger2 本身了,遵循循序漸進簡單易懂的原則,所以要花費一定篇幅。

那么首先要明確了解一下dagger2是什么:
Dagger1
這個版本不是這篇文章的重點,所以我只是簡略地說一下。不管怎樣,Dagger1還是做了很多的貢獻,可以說是如今Android上最流行的依賴注入框架。它是由Square公司受到Guice啟發(fā)創(chuàng)建的。
基本特點:
多個注入點:依賴,通過injected
多種綁定方法:依賴,通過provided
多個modules:實現某種功能的綁定集合
多個對象圖: 實現一個范圍的modules集合

Dagger1是在編譯的時候實行綁定,不過也用到了反射機制。但這個反射不是用來實例化對象的,而是用于圖的構成。Dagger會在運行的時候去檢測是否一切都正常工作,所以使用的時候會付出一些代價:偶爾會無效和調試困難。
Dagger2
Dagger2是Dagger1的分支,由谷歌公司接手開發(fā),目前的版本是2.0。Dagger2是受到AutoValue項目的啟發(fā)。 剛開始,Dagger2解決問題的基本思想是:利用生成和寫的代碼混合達到看似所有的產生和提供依賴的代碼都是手寫的樣子。
如果我們將Dagger2和1比較,他們兩個在很多方面都非常相似,但也有很重要的區(qū)別,如下:
再也沒有使用反射:圖的驗證、配置和預先設置都在編譯的時候執(zhí)行。
容易調試和可跟蹤:完全具體地調用提供和創(chuàng)建的堆棧
更好的性能:谷歌聲稱他們提高了13%的處理性能
代碼混淆:使用派遣方法,就如同自己寫的代碼一樣

當然所有這些很棒的特點都需要付出一個代價,那就是缺乏靈活性,例如:Dagger2沒用反射所以沒有動態(tài)機制。

是不是蒙蔽了??!!
廢話少說,上代碼,來看下如何找Android 中使用dagger2。
首先在整個項目的gradle文件中加入即時編譯生成代碼的apt插件依賴(或者也可以寫到下面moudel的gradle文件中)

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'//這里是添加的,也可以寫到下面moudel的gradle文件中
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

然后在moudel的gradle文件中加入相關依賴:

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt' //加入即時編譯插件apt
android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "zhangzhe.daggerdemo"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'

    apt 'com.google.dagger:dagger-compiler:2.0'//這里是添加的
    compile 'com.google.dagger:dagger:2.0'//這里是添加的
    provided 'javax.annotation:jsr250-api:1.0'//這里是添加的
}

先不講dagger2的理論一些名稱直接擼代碼;
以Android當前流行的mvp模式為例,寫一個簡要的登錄demo。

1.先建立登錄的activity 作為view層;

public class LoginActivity extends AppCompatActivity  {
 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
  
}
}

2.建立ILoginContract協議接口,定義view層和presenter層的邏輯。

public interface ILoginContract {
interface ILoginPresenter {
    void login(String name,String pwd);
}

interface ILoginView<ILoginPresenter>{
    void loginok();
    void loginErro();
}

}

3.建立presenter的實現類

public class LoginPresenter implements     ILoginContract.ILoginPresenter {
ILoginContract.ILoginView view;


public LoginPresenter(ILoginContract.ILoginView view) {
    this.view = view;
}

@Override
public void login(String name, String pwd) {

}
}

我們按常規(guī)的方式會把LoginPresenter 在activity中聲明成員變量,并new 出來如下:

 public class LoginActivity extends AppCompatActivity  implements ILoginContract.ILoginView{
    
   LoginPresenter  presenter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
       presenter = new LoginPresenter(this);//這里有問題
    }

    @Override
    public void loginok() {

    }

    @Override
    public void loginErro() {

    }
}

如上,這里的presenter是new出來的,達到互相依賴的關系,這樣就把彼此僅僅的耦合在一起了,一旦presenter的構造方法改變就要同時改變activity中的代碼,這不是我們想要的。
那么dagger2 是如何注入的呢;
首先我們需要新建兩個類文件:
Moudule類

@Module
public class LoginMoudule {
private final ILoginContract.ILoginView view;
public LoginMoudule(ILoginContract.ILoginView view) {
    this.view = view;
}
@Provides
ILoginContract.ILoginView provideLoginView(){
    return view;
}
}

Component類

@Component(modules = LoginMoudule.class)
public interface LoginComponent {
 void inject(LoginActivity activity);
}

可見moudule類用@Module 注解,構造方法中注入view層, 并用@Provides注解一個返回ILoginView的方法;Component類用@Component(modules = LoginMoudule.class)注解可見Component與LoginMoudule.class必然存在某種關系,并inject方法把activity聯系起來,這樣這幾個類就肯定通過某種方法聯系起來了,但這些聯系并不需要我們程序員去寫什么了。

接下來就是對view和presenter兩個類內部進行改造:activity

public class LoginActivity extends AppCompatActivity  implements ILoginContract.ILoginView{
    @Inject//這里加注解
    LoginPresenter presenter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
    }

    @Override
    public void loginok() {

    }

    @Override
    public void loginErro() {

    }
}

presenter類

public class LoginPresenter implements ILoginContract.ILoginPresenter {
ILoginContract.ILoginView view;

@Inject//這里注解
public LoginPresenter(ILoginContract.ILoginView view) {
    this.view = view;
}

@Override
public void login(String name, String pwd) {
}
}

在activity中的依賴的presenter添加@Inject注解,同時在presenter中的構造方法同時加這個@Inject的注解,之后build一下整個項目,在項目的project視圖下的build的文件夾下生成了如下的幾個類,這就是dagger2 通過apt生成的輔助類,也是dagger2的玄機所在。

Paste_Image.png

回到activity中:

public class LoginActivity extends AppCompatActivity  implements ILoginContract.ILoginView{
    @Inject
    ILoginContract.ILoginPresenter presenter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
//添加此句
        DaggerLoginComponent.builder().loginMoudule(new LoginMoudule(this)).build().inject(this);
    }

    @Override
    public void loginok() {

    }

    @Override
    public void loginErro() {

    }
}

dagger2生成的義Dagger前綴的Component內部完成了這一系列注入過程。
到此為止mvp中v和p的互相注入通過dagger2已經完成,此時可以測試一下,看presenter是否會報空指針。你可能會說了,wtf(what the fuck)這么麻煩!!呵呵,和我一開始一樣的。但是想想框架不一定就是能滿足程序員的懶,框架麻煩但是能讓我們的程序更健壯,或者維護起來會省很多事啊!想你說的 ,懶!沒辦法。
好今天就到這里,接下來會詳細介紹dagger2 的細節(jié),每天學一點點,厚積薄發(fā)。

每天發(fā)的東西都是我正在學習的東西,學習的同時,與更多人分享,一能增進我的記憶,同時提出自己的見解與大家互相促進提高,同時也希望收到拍磚

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容