【Android 進階】Dagger2 系列:入門案例一

版權聲明:本文爲博主原創文章,轉載請註明出處。 https://blog.csdn.net/leaf_130/article/details/71512695

歡迎關注我的微信公衆號,不只是原創技術分享,更多的是生活的思考和總結。

這裏寫圖片描述

介紹

A fast dependency injector for Android and Java.
一個在 Android 和 Java 平臺上使用的快速的依賴注入框架。
類似 java 開發中的 spring 框架,但使用難度比 spring 大一點點。
依賴注入框架主要用於模塊間解耦,提高代碼的健壯性和可維護性。

幾個必須知道的概念:

什麼是依賴:

如果在 Class A 中,有 Class B 的實例,則稱 Class A 對 Class B 有一個依賴。

什麼是依賴注入:

依賴注入就是非自己主動初始化依賴,而通過外部來傳入依賴的方式,簡單來說就是不使用 new 來創建依賴對象。

三大元素:

必不可少的元素有三種,Module,Component,Container

image
- Container 擁有者,容器等意思,其中 Activity 就是 Dagger2 中的 Container.
- Component Acitvity 和 依賴對象之間的一個橋樑。
- Module 就是負責提供對象的。

用到的註解如下:

@Inject:
通常在需要依賴的地方使用這個註解。換句話說,你用它告訴 Dagger 這個類或者字段需要依賴注入。這樣,Dagger 就會構造一個這個類的實例並滿足他們的依賴。

@Module:
Modules 類裏面的方法專門提供依賴,所以我們定義一個類,用 @Module 註解,這樣 Dagger 在構造類的實例
時候,就知道從哪裏去找到需要的 依賴。modules 的一個重要特徵是它們設計爲分區並組合在一起(比如說,
我們的 app 中可以有多個組成在一起 的modules)

@Provide:
在 modules 中,我們定義的方法是用這個註解,以此來告訴 Dagger 我們想要構造對象並提供這些依賴。

@Component:
Components 從根本上來說就是一個注入器,也可以說是 @Inject 和 @Module 的橋樑,它的主要作用就是連接這兩個部分。 Components 可以提供所有定義了的類型的實例,比如:我們必須用 @Component 註解一個接口然後列出所有的

官方 Github 地址以及 API 說明文檔::

google/dagger

說明文檔

使用準備:

project 的 build.gradle 添加

dependencies {
     ... // 其他 classpath
     classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //添加 apt 命令
 }


module 的 build.gradle 添加

// 添加其他插件
apply plugin: 'com.neenbedankt.android-apt'//添加 apt 命令

dependencies {
    apt 'com.google.dagger:dagger-compiler:2.0.2' //指定註解處理器
    compile 'com.google.dagger:dagger:2.0.2'  //dagger 公用 api
    provided 'org.glassfish:javax.annotation:10.0-b28'  //添加 android 缺失的部分 javax 註解
}

直接從代碼出發吧

代碼完整,可以直接粘貼到自己 AS 驗證。

看一個簡單的例子:

代碼如下:

MainActivity.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:直接依賴注入 ApiService 對象
 */
public class MainActivity extends AppCompatActivity {
    @Inject
    ApiService mApiService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //rebuild一下,自動生成 DaggerUserComponet 類
        DaggerUserComponet.create().inject(this);
        mApiService.register();
    }
}

ApiService.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:
 */
public class ApiService {

    public void register(){
        Log.e("ApiService","register");
    }
}

UserModule.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:提供實例的 Module
 */
@Module
public class UserModule {
    @Provides
    public ApiService provideApiService(){
        Log.e("UserModule","provideUserManger");
        return new ApiService();
    }
}

UserComponet

/**
 * Created by Veyron on 2017/5/9.
 * Function:Activity 和 Module 之間的橋樑
 * @Component(modules = {UserModule.class}) 表示和 Module 對接
 *
 * void inject(MainActivity activity);表示在 MainActivity 中注入
 */
@Component(modules = {UserModule.class})
public interface UserComponet {

     void inject(MainActivity activity);
}

輸出:

E/UserModule: provideApiService
E/ApiService: register

更復雜一點的例子:

MainActivity.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:直接依賴注入 UserManger 對象
 */
public class MainActivity extends AppCompatActivity {
  /*  @Inject
    ApiService mApiService;*/
    @Inject
    UserManger mUserManger;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DaggerUserComponet.builder()
                .userModule(new UserModule()).build().inject(this);
        //DaggerUserComponet.create().inject(this); 等價上面

        mUserManger.register();
    }
}

ApiService.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:直接依賴注入 UserManger 對象
 */
public class ApiService {

    //當module裏面沒有提供本類的對象,默認調用下面這個 @Inject 註釋的構造函數(只能聲明一個)
    @Inject
    public ApiService(){
        Log.e("ApiService","ApiService的構造函數");
    }

  /*  @Inject
    public ApiService(String url){
        Log.e("ApiService","url---");
    }*/


    public void register(){
        Log.e("ApiService","register");
    }
}

UserModule.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:
 */
@Module
public class UserModule {
    @Provides
    public ApiService provideApiService(){
        Log.e("UserModule","provideApiService-");
        return new ApiService();
    }

    @Provides
    public String url(){
        return "url";
    }
    // 將會調用這個 public ApiService(String url) 方法


    //單獨調用本方法的話,apiService 的對象是上面提供的,另一種使用 apiservice 的構造方法
    @Provides
    public UserManger provideUserManger(ApiService apiService){
        Log.e("UserModule","provideUserManger");
        return new UserManger(apiService);
    }
}

UserComponet.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:Activity 和 Module 之間的橋樑
 * @Component(modules = {UserModule.class}) 表示和 Module 對接
 *
 * void inject(MainActivity activity);表示在 MainActivity 中注入
 */
@Component(modules = {UserModule.class})
public interface UserComponet {

     void inject(MainActivity activity);
}

輸出如下:

E/UserModule: provideApiService
E/ApiService: ApiService 的構造函數
E/UserModule: provideUserManger
E/UserManger: register
E/ApiService: register

更復雜點

第二個例子其中,將 UserModule.java,UserModule.java 改動如下:

UserModule.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:
 */
@Module
public class UserModule {
    /*@Provides
    public ApiService provideApiService(){
        Log.e("UserModule","provideApiService");
        return new ApiService();
    }*/

    @Provides
    public String url(){
        return "傳給 ApiService 構造函數的參數";
    }
    // 將會調用這個 public ApiService(String url) 方法


    //單獨調用本方法的話,apiService 的對象是上面提供的,另一種使用 apiservice 的構造方法
    @Provides
    public UserManger provideUserManger(ApiService apiService){
        Log.e("UserModule","provideUserManger");
        return new UserManger(apiService);
    }
}

ApiService.java

/**
 * Created by Veyron on 2017/5/9.
 * Function:@Inject 聲明的構造函數只能有一個
 */
public class ApiService {

    //當module裏面沒有提供本類的對象,默認調用下面這個 @Inject 註釋的構造函數(只能聲明一個)
    /*@Inject
    public ApiService(){
        Log.e("ApiService","ApiService的構造函數");
    }*/

    @Inject
    public ApiService(String url){
        Log.e("ApiService","url="+url);
    }


    public void register(){
        Log.e("ApiService","register");
    }
}

輸出是:

E/ApiService: url=傳給ApiService構造函數的參數
E/UserModule: provideUserManger
E/UserManger: register
E/ApiService: register

看了輸出,再參考下代碼,其實就知道是怎麼回事了。
可以得到一點結論就是:在 UserModule 中需要 ApiService 對象,但是 UserModule 中並沒提供,那麼就去查看 ApiService 中有沒有 @Inject 聲明的構造函數,如果有且是無參構造函數,那麼 UserModule 中就相當拿到了 ApiService 對象。如果是有參的構造函數,則 UserModule 中必須有提供該參數的實例,如本例子中的 public String url() 函數,返回的 String 就是給構造函數當參數的,那麼 UserModule 中就等於有了 ApiService 對象。

聲明

建議把上面的例子都運行一遍,就會有體會 Dagger2 的使用是怎樣的。
篇幅有限,Dagger2 使用方式也有很多, 下一篇接着介紹 其他例子。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章