編輯:關於android開發
什麼是Dagger2
Dagger是為Android和Java平台提供的一個完全靜態的,在編譯時進行依賴注入的框架,原來是由Square公司維護,現在由Google維護。
我們知道Dagger是一個依賴注入的框架,那麼什麼是依賴注入呢?
我們在activity中有可能會用到很多很多的類,這些類要在activity中進行實例化,這樣就導致我們的activity非常依賴這麼多的類,這樣的程序耦合非常
嚴重,不便於維護和擴展,有什麼辦法可以不去依賴這些類呢,這時候就需要有一個容器(IoC),將這些類放到這個容器裡並實例化,我們activity在用
到的時候去容器裡面取就可以了,我們從依賴類到依賴這個容器,實現了解耦,這就是我所理解的依賴注入,即所謂控制反轉;
簡單的說 Dagger就是用來創造這個容器,所有需要被依賴的對象在Dagger的容器中實例化,並通過Dagger注入到合適的地方,實現解耦,MVP框架就是為解耦而生,因此MVP和Dagger是絕配;
舉個栗子?
通常情況下我們引用一個類的做法:
我們先定義一個簡單的類:
1 public class User { 2 private String name; 3 4 public String getName() { 5 return name; 6 } 7 8 public void setName(String name) { 9 this.name = name; 10 } 11 }
在Activity中對其操作
1 private void initData() { 2 3 User user = new User(); 4 5 user.setName("測試"); 6 }
以上是最普通的用法
接下來我們來看Dagger2的用法
我們先來配置一下Dagger2
首先在項目的 build.gradle:
1 dependencies { 2 classpath 'com.android.tools.build:gradle:1.5.0' 3 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 4 classpath 'me.tatarka:gradle-retrolambda:3.2.0' 5 // NOTE: Do not place your application dependencies here; they belong 6 // in the individual module build.gradle files 7 }
然後是APP的 build.gradle
1 apply plugin: 'com.android.application' 2 apply plugin: 'com.neenbedankt.android-apt' 3 apply plugin: 'me.tatarka.retrolambda' 4 android { 5 compileSdkVersion 23 6 buildToolsVersion "23.0.1" 7 8 defaultConfig { 9 applicationId "jiao.com.jiaoproject" 10 minSdkVersion 15 11 targetSdkVersion 23 12 versionCode 1 13 versionName "1.0" 14 } 15 buildTypes { 16 release { 17 minifyEnabled false 18 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 } 20 } 21 22 compileOptions { 23 sourceCompatibility JavaVersion.VERSION_1_8 24 } 25 26 } 27 28 dependencies { 29 compile fileTree(dir: 'libs', include: ['*.jar']) 30 testCompile 'junit:junit:4.12' 31 compile 'com.android.support:appcompat-v7:23.3.0' 32 compile 'com.android.support:design:23.3.0' 33 apt 'com.google.dagger:dagger-compiler:2.2' 34 provided 'org.glassfish:javax.annotation:10.0-b28' 35 compile 'com.google.dagger:dagger:2.2' 36 compile 'com.jakewharton:butterknife:7.0.1' 37 compile 'com.squareup.okhttp3:logging-interceptor:3.3.0' 38 }
首先
1 public class User { 2 private String name; 3 4 @Inject 5 public User() { 6 } 7 8 public String getName() { 9 return name; 10 } 11 12 public void setName(String name) { 13 this.name = name; 14 } 15 }
發現有什麼變化了沒?@Inject是什麼東東?待會我們來說;
接著我們看怎麼使用
1 @Inject 2 User user; 3 4 private void initData() { 5 6 user.setName("測試"); 7 }
這時候我們允許程序發現空指針了;因為還缺少一個東西;
1 @Component 2 public interface ActivityComponent { 3 4 void inject(MainActivity MainActivity); 5 }
加上這個類之後 並且在Activity中對其初始化 完整代碼如下:
1 @Inject 2 User user; 3 4 private void initData() { 5 DaggerActivityComponent.builder().build().inject(this); 6 user.setName("測試"); 7 }
這時候發現我們的user對象可以正常使用了;看上去感覺挺復雜的,但是對於大型項目引用的類過多的時候,Dagger的優勢就體現出來了;
接下來我一一解答你們的疑惑;
首先我們來了解這幾個基礎概念:
看了這些概念我們回到剛才的例子當中:
我們對User的構造函數進行了 @Inject的標注 意思就是告訴Dagger2 如果有誰要使用User這個類,我標注的這個構造函數,你可以直接用來實例化該類;
然後我們在Activity中對User也進行了@Inject的標注 意思是告訴Dagger2 這個類需要被注入,簡單的說就是 這個類我要用,你幫我實例化;
細心的讀者可能會發現 這樣會不會太簡單了,是的 是太簡單了不太正常,哈哈,上面的例子中還有一個標注@Component 光靠@Inject的標注是不足以完成注入的 我們需要用@Component來完成注入;
上例中被@Component標記的ActivityComponent接口就是一個注入器; void inject(MainActivity MainActivity);的意思是MainActivity中要用到這個注入器然後我們在MainActivity中對注入器進行初始化 DaggerActivityComponent.builder().build().inject(this); 然後Activity中所有被@Inject標記的類,都會通過ActivityComponent來進行初始化;
我們再把上例中的注入過程梳理一下:
1、首先定義一個類User 並在其構造函數用@Inject標注,表示告訴Dagger2這是我的構造函數,如果有地方要用到我,就用該構造函數對我實例化;
2、創建一個@Component標注的注入器接口,並在注入器中使用 void inject(MainActivity MainActivity);來表明哪裡要用到注入器;
這裡表示MainActivity中要用到該注入器
3、在MainActivity中對注入器進行初始化DaggerActivityComponent.builder().build().inject(this); 初始化後該注入器就可以正常使用了;
4、在MainActivity中對需要注入的類 User用@Inject進行標注,表示該類需要被注入,即實例化;
注意:在代碼編寫過程中 我們會發現DaggerActivityComponent會不存在,這是因為注入器是在編譯的過程中才生成,所以我們在對注入器編寫完成後
Make Project 一下就會生成DaggerActivityComponent
————————————————————————————————————————————————————————————————————————————————
現在我們已經明白了@InJect @Component的作用了,接下來我們來研究@Module和@Provide
通過上面的例子我們發現 @Inject是對類的構造函數進行標注來進行實例化的,但是有些類,比如第三方OkHttpClient,我們是無法對其源碼進行修改的
即對其構造函數進行標注,這個時候我們就用到了@Module
@Module是什麼意思呢 @Module是和@Component配合使用的 意思就是告訴注入器,如果你在實例化對象的時候,沒有找到合適的構造函數,你就來我這裡找,@Module通常標注一個類,該類裡面可以實例化各種類,Component在注入對象的時候先去Module中找,如果找不到就會檢查所有被@Inject標注的構造函數;所以我們可以把OkHttpClient放到Module中;
1 @Module 2 public class ActivityMoudle { 3 4 @Provides 5 @Singleton 6 OkHttpClient provideOkHttpClient() { 7 HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); 8 loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 9 10 Interceptor apikey = chain -> chain.proceed(chain.request().newBuilder() 11 .addHeader("apikey", Constants.Api_Key).build()); 12 13 OkHttpClient okHttpClient = new OkHttpClient.Builder() 14 .readTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS) 15 .connectTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS) 16 .addInterceptor(apikey) 17 .addInterceptor(loggingInterceptor) 18 .build(); 19 20 return okHttpClient; 21 } 22 23 }
以上代碼我們不需要知道是干嘛的,我們只知道該類中的方法返回一個okHttpClient的實例;
一個被@Module標注的類用來返回一個okHttpClient的實例;
我們再來看一下在Component中的代碼:
1 @Singleton 2 @Component(modules = ActivityMoudle.class) 3 public interface ActivityComponent { 4 5 void inject(MainActivity MainActivity); 6 }
可以看到標注頭多了@Component(modules = ActivityMoudle.class),表示告訴注入器如果你要注入的類沒有找到構造函數,你就去ActivityMoudle.class中找
@Provide 用來標注一個方法,告訴注入器,我標注的方法你可以用來提供實例;
@Singleton 顧名思義,標注該實例化的對象為單例
然後我們在Activity直接標注使用就可以了
1 @Inject 2 OkHttpClient okHttpClient;
至此我們有兩種方式可以提供依賴,一個是注解了@Inject的構造方法,一個是在Module裡提供的依賴,那麼Dagger2是怎麼選擇依賴提供的呢,規則是這樣的:
步驟3:若不存在創建類方法,則查找Inject注解的構造函數,看構造函數是否存在參數
步驟3.1:若存在參數,則從步驟1開始依次初始化每個參數
這次依賴注入就先寫這麼多,Dagger結合MVP實現完美的配合,小伙伴們可以自己去研究一下其中的奧妙~
Android 貝塞爾曲線的淺析,android貝塞爾淺析博客也開了挺長時間了,一直都沒有來寫博客,主要原因是自己懶~~~此篇博客算是給2017年一個好的開始,同時也給2
簡單回調機制的基本建立,簡單回調機制建立簡單回調機制的建立主要分為下面幾步: 1.寫一個回調類,寫出需要的構造方法 2.定義一個接口,裡面寫一個抽象方法,方法體(Stri
Kotlin中功能操作與集合(KAD 11),作者:Antonio Leiva 時間:Feb 2, 2017 原文鏈接:https://antonioleiva.com/
Android數據存儲的三種方式介紹(SharedPrefrences,File,SQLite) 1,使用SharedPrefrences 用於簡單少量的數據,數據的