android開源庫---Dagger2入門學習(簡單使用)
Dagger2依賴注入
前面我們做好學習準備接下來就要研究如何使用了,俗話說的好,一個東西需要先會用,然後才更好的學習原理。
一、匯入Dagger2
在工程的build.gradle檔案中新增android-apt外掛(該外掛後面介紹)
buildscript {
....
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
// 新增android-apt 外掛
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
在app的中的build.gradle檔案中新增配置
apply plugin: 'com.android.application'
// 應用外掛
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.mahao.alex.architecture"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar' ])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
// dagger 2 的配置
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
compile 'org.glassfish:javax.annotation:10.0-b28'// 新增java 註解庫
}
android-apt是Gradle編譯器的外掛,根據其官方文件,主要兩個目的:
- 編譯時使用該工具,最終打包時不會將該外掛打入到apk中。
- 能夠根據設定的源路徑,在編譯時期生成相應程式碼。
二、寫個Demo
這個就依照上篇的女孩依賴於一個男孩,這我們再加一個依賴就是父母(畢竟男人不一定靠的住^(* ̄(oo) ̄)^)。好了開始寫
寫一個Module類,管理上面的依賴。
@Module
public class GirlModule {
@Provides
public Boy provideBoy(){
return new Boy();
}
@Provides
public Parents provideParents(){
return new Parents();
}
}
寫一個Component類,來連線Module和你的Girl。
@Component(modules = GirlModule.class)
public interface GirlComponent {
void inject(Girl girl);
}
到了這裡不要急著往下寫,先執行一下你的程式碼。(下面再說為什麼)
好了,繼續下一步,重寫Girl類
public class Girl {
@Inject
Boy boy;
@Inject
Parents parents;
public Girl() {
DaggerGirlComponent
.builder()
.girlModule(new GirlModule())
.build()
.inject(this);
Log.d("Girl", "new Girl()");
}
}
首先我們可以看到在使用過程出現了很多註解:
- @Module:作為例項物件的容器。
- @Provides:標註能夠提供例項化物件的方法。
- @Component:作為橋樑,注入物件的通道。
- @Inject:需要注入的方法
分析
我們可以看到在GirlModule 是用一個@Module註解的類,這是作為例項物件的容器,用於管理,裡面的方法是使用@Provides註解,可以看出來其實就是給你提供依賴的方法。
我們知道了管理並提供依賴的類,那麼我們就可以通過它來直接使用依賴。但是Dagger2為了解耦,提供了一箇中介,@Component註解,這是作為橋樑將依賴和需求(girl)聯絡起來。
@Component(modules = GirlModule.class)
public interface GirlComponent {
void inject(Girl girl);
}
那麼我們來看看@Component的官方文件。
* Annotates an interface or abstract class for which a fully-formed, dependency-injected
* implementation is to be generated from a set of {@linkplain #modules}.
說的是這個註解只能用於介面或者抽象類。將程式碼改成下面,輸出也是一樣的。
@Component(modules = GirlModule.class)
public abstract GirlComponent {
void inject(Girl girl);
}
還有 @Inject註解 就是使用的時候的注入方法。
@Inject
Boy boy;
上面的程式碼表示Boy 這個屬性你不用像一般情況去初始化(boy= new Boy ()),它能給你自動尋找依賴。
但是這樣就可以了麼?當然是不行,你都沒有和前面的聯絡其來。所以還需要如下程式碼:
DaggerGirlComponent
.builder()
.girlModule(new GirlModule())
.build()
.inject(this);
這裡你就會看到一個你沒有建立的類是,這個是由apt工具幫我們生成的類,但是是在編譯時期生成程式碼,所以為什麼前面要你們先執行下(我之前就是一頭霧水,大部分人都說生成沒說怎麼生成,搞的我一度誤解)
這裡tip一下
在android-apt的文件中,也推薦使用這種方式。因為,編譯時期生成程式碼的類庫在執行期並不需要,那麼將其分為兩個庫,(執行類庫dagger)和(編譯器生成程式碼類庫(dagger-compiler)),那麼在打包時,就不需要將dagger-compiler打入其中(用不到),減小APK 的大小。
DaggerGirlComponent實現了GirlComponent介面。
通過girlModule()將我們的依賴提供者傳入,通過inject()將我們的Girl物件傳入,這樣就達到了中間人的目的。
package com.example.admin.dagger2.gg;
import dagger.MembersInjector;
import dagger.internal.Preconditions;
import javax.annotation.Generated;
import javax.inject.Provider;
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://google.github.io/dagger"
)
public final class DaggerGirlComponent implements GirlComponent {
private Provider<Boy> provideBoyProvider;
private Provider<Parents> provideParentsProvider;
private MembersInjector<Girl> girlMembersInjector;
private DaggerGirlComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static GirlComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.provideBoyProvider = GirlModule_ProvideBoyFactory.create(builder.girlModule);
this.provideParentsProvider = GirlModule_ProvideParentsFactory.create(builder.girlModule);
this.girlMembersInjector =
Girl_MembersInjector.create(provideBoyProvider, provideParentsProvider);
}
@Override
public void inject(Girl girl) {
girlMembersInjector.injectMembers(girl);
}
public static final class Builder {
private GirlModule girlModule;
private Builder() {}
public GirlComponent build() {
if (girlModule == null) {
this.girlModule = new GirlModule();
}
return new DaggerGirlComponent(this);
}
public Builder girlModule(GirlModule girlModule) {
this.girlModule = Preconditions.checkNotNull(girlModule);
return this;
}
}
}
到這裡基本的入門使用就知道。
這裡想必還是一頭霧水感覺不出有什麼用處,不要著急,飯要一口一口吃,我們先了解使用,然後再慢慢一步一步瞭解。