Dagger2 (一) 入坑篇


為什么是Dagger2

為了更好的了解Dagger2,請先閱讀RoboGuice篇了解依賴注入。

官方文檔稱,依賴注入這種技術已經在存在多年了,為什么Dagger2要造輪子?

Dagger2是第一個全部使用自動生成代碼的框架。

框架生成的代碼就像我們自己手寫的,可以輕易進行調試和測試,並且很容易了解其原理。

一.接入

Dagger2使用了生成代碼的方式,這里需要apt的插件。

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0-beta6'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}

而Dagger2的主要包中,方法則特別少,主要是編譯時提供。

dependencies {
    compile 'com.google.dagger:dagger:2.0.2'
    provided 'com.google.dagger:dagger-compiler:2.0.2'
    provided 'org.glassfish:javax.annotation:10.0-b28'
}

由此,接入框架便成功了。

二.視圖注入

相對於RoboGuice來講,Dagger2是不支持視圖注入的,所以如果選用Dagger2進行對象注入框架的話,可以考慮Dagger2+ButterKnife的配合使用,Dagger2和ButterKnife都沒有使用反射機制並且專注於對象或視圖的注入。

三.對象注入

Dagger2的對象注入同RoboGuice略有不同,但也是和其他注入框架類似,還是使用之前的例子,下面是一個用來儲存用戶信息的model。注意Dagger2不會默認使用默認構造方法創建以來,必須手動指定。

public class UserInfo {
    private String userId;
    private String token;

    @Inject
    UserInfo(){
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public boolean isLogin(){
        return !TextUtils.isEmpty(token);
    }
}

當我直接使用Inject這個UserInfo的對象的時候,框架會為我們默認使用構造方法進行初始化。

public class MainActivity extends AppCompatActivity {

    @Inject
    UserInfo userInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        userInfo.setToken("testToken");
        userInfo.setUserId("123456");
    }
}

四.Module與Component

Dagger2相比於RoboGuice更為靈活,其中Module的定義與RoboGuice相同,主要指提供依賴的模塊,而Component則是一個新出現的詞。

Component英文原意為組件,但在這里面就是一個注入器,相當於RoboGuice中的RoboInject,是提供依賴及使用依賴之間的橋梁,而Dagger2更為靈活的是,我們可以自定義這個注入器。

廢話不多說,上代碼。

首先我們定義一個Module,與RoboGuice不同的是,我們只需要加入注解即可,不需要繼承自Dagger2的Module類。

這里我們提供了Application和Context的依賴。

@Module
public class ApplicationModule {

    private Application application;

    public ApplicationModule(Application application) {
        this.application = application;
    }

    @Singleton
    @Provides
    public Application application() {
        return application;
    }

    @Singleton
    @Provides
    public Context context() {
        return application;
    }
}

接下來定義另一個Module,GsonModule。

還是熟悉的標有需要serializeNulls的Gson對象。

@Module
public class GsonModule {

    @Provides
    public Gson provideGson() {
        return new GsonBuilder().
                serializeNulls().
                create();
    }
}

接下來我們定義一個注入器,ApplicationComponent。

定義方法也很簡單,注解標有Component,並且可以指定注入器可以注入的模塊。

其中inject方法稍后講解。

@Component(modules = {ApplicationModule.class, GsonModule.class})
public interface ApplicationComponent {
    void inject(MainActivity activity);
}

好了,寫到這,可以放心大膽的編譯一下項目了,這時Dagger2會自動生成一些代碼,生成的代碼是Component前加上Dagger的類,上面的例子生成的就是DaggerApplicationComponent。

如何使用注入呢?我們用以下方法初始化這個注入器ApplicationComponent。

public class DaggerApplication extends Application {

    private static ApplicationComponent component;

    @Override
    public void onCreate() {
        super.onCreate();
        component = DaggerApplicationComponent.builder().
                applicationModule(new ApplicationModule(this)).
                gsonModule(new GsonModule()).
                build();
    }

    public static ApplicationComponent Component() {
        return component;
    }
}

這里只相當於注入器的初始化,並沒有真正的注入對象,下面我們在MainActivity中注入對象。

public class MainActivity extends AppCompatActivity {

    @Inject
    Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        component().inject(this);
        Log.e(TAG, "onCreate: " + context.getPackageName());
    }

    public ApplicationComponent component() {
        return DaggerApplication.Component();
    }
}

運行一下,可以看到打印出了日志,至此,我們第一個較為復雜的注入就完成了。這里注入的其實是Application的Context,並不是Activity的Context,為什么呢,以為我們在Application的Module中定義了Context的Provider。

03-20 22:51:25.046 32476-32476/github.pedroneer.dagger2 E/MainActivity: onCreate: github.pedroneer.dagger2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM