為什麼是Dagger2 為了更好的瞭解Dagger2,請先閱讀 "RoboGuice" 篇瞭解依賴註入。 官方文檔稱,依賴註入這種技術已經在存在多年了,為什麼Dagger2要造輪子? 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