510
技術社區[雲棲]
安卓平台上的依賴注入(一)
剛開始學習軟件工程的時候,我們經常會碰到像這樣的事情:
軟件應該符合 SOLID 原則。
但這句話實際是什麼意思?讓我們看看 SOLID 中每個字母在架構裏所代表的重要含義,例如:
- S - 單職責原則
- O - 開閉原則
- L - Liskov 替換原則
- I - 接口分離原則
- D - 依賴反轉原則 這也是依賴注入dependency injection的核心概念。
簡單來說,我們需要提供一個類,這個類有它所需要的所有對象,以便實現其功能。
概述
依賴注入聽起來像是描述非常複雜的東西的一個術語,但實際上它很簡單,看下麵這個例子你就明白了:
class NoDependencyInjection {
private Dependency d;
public NoDependencyInjection() {
d = new Dependency();
}
}
class DependencyInjection {
private Dependency d;
public DependencyInjection(Dependency d) {
this.d = d;
}
}
正如我們所見,第一種情況是我們在構造器裏創建了依賴對象,但在第二種情況下,它作為參數被傳遞給構造器,這就是我們所說的依賴注入dependency injection。這樣做是為了讓我們所寫的類不依靠特定依賴關係的實現,卻能直接使用它。
參數傳遞的目標是構造器,我們就稱之為構造器依賴注入;或者是某個方法,就稱之為方法依賴注入:
class Example {
private ConstructorDependency cd;
private MethodDependency md;
Example(ConstructorDependency cd) {
this.cd = cd; //Constructor Dependency Injection
}
public setMethodDependency(MethodDependency md) {
this.md = md; //Method Dependency Injection
}
}
要是你想總體深入地了解依賴注入,可以看看由 Dan Lew 發表的精彩的演講,事實上是這個演講啟迪了這篇概述。
在 Android 平台,當需要框架來處理依賴注入這個特殊的問題時,我們有不同的選擇,其中最有名的框架就是 Dagger 2。它最開始是由 Square 公司(LCTT 譯注:Square 是美國一家移動支付公司)的一些很棒的開發者開發出來的,然後慢慢發展成由 Google 自己開發。首先開發出來的是 Dagger 1,然後 Big G 接手這個項目發布了第二個版本,做了很多改動,比如以注解annotation為基礎,在編譯的時候完成其任務。
導入框架
安裝 Dagger 並不難,但需要導入 android-apt
插件,通過向項目的根目錄下的 build.gradle
文件中添加它的依賴關係:
buildscript{
...
dependencies{
...
classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’
}
}
然後,我們需要將 android-apt
插件應用到項目 build.gradle
文件,放在文件頂部 Android application 那一句的下一行:
apply plugin: ‘com.neenbedankt.android-apt’
這個時候,我們隻用添加依賴關係,然後就能使用庫及其注解annotation了:
dependencies{
...
compile ‘com.google.dagger:dagger:2.6’
apt ‘com.google.dagger:dagger-compiler:2.6’
provided ‘javax.annotation:jsr250-api:1.0’
}
需要加上最後一個依賴關係是因為 @Generated 注解在 Android 裏還不可用,但它是原生的 Java 注解。
Dagger 模塊
要注入依賴,首先需要告訴框架我們能提供什麼(比如說上下文)以及特定的對象應該怎樣創建。為了完成注入,我們用 @Module
注釋對一個特殊的類進行了注解(這樣 Dagger 就能識別它了),尋找@Provide
注解的方法,生成圖表,能夠返回我們所請求的對象。
看下麵的例子,這裏我們創建了一個模塊,它會返回給我們 ConnectivityManager
,所以我們要把Context
對象傳給這個模塊的構造器。
@Module
public class ApplicationModule {
private final Context context;
public ApplicationModule(Context context) {
this.context = context;
}
@Provides @Singleton
public Context providesContext() {
return context;
}
@Provides @Singleton
public ConnectivityManager providesConnectivityManager(Context context) {
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
}
Dagger 中十分有意思的一點是簡單地注解一個方法來提供一個單例(Singleton),就能處理所有從 Java 中繼承過來的問題。
組件
當我們有一個模塊的時候,我們需要告訴 Dagger 想把依賴注入到哪裏:我們在一個組件Component裏完成依賴注入,這是一個我們特別創建的特殊注解接口。我們在這個接口裏創造不同的方法,而接口的參數是我們想注入依賴關係的類。
下麵給出一個例子並告訴 Dagger 我們想要 MainActivity
類能夠接受 ConnectivityManager
(或者在圖表裏的其它依賴對象)。我們隻要做類似以下的事:
@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
void inject(MainActivity activity);
}
正如我們所見,@Component 注解有幾個參數,一個是所支持的模塊的數組,代表它能提供的依賴。這裏既可以是
Context
也可以是ConnectivityManager
,因為它們在ApplicationModule
類中有聲明。
用法
這時,我們要做的是盡快創建組件(比如在應用的 onCreate
階段)並返回它,那麼類就能用它來注入依賴了:
為了讓框架自動生成
DaggerApplicationComponent
,我們需要構建項目以便 Dagger 能夠掃描我們的代碼,並生成我們需要的部分。
在 MainActivity
裏,我們要做的兩件事是用 @Inject
注解符對想要注入的屬性進行注解,調用我們在 ApplicationComponent
接口中聲明的方法(請注意後麵一部分會因我們使用的注入類型的不同而變化,但這裏簡單起見我們不去管它),然後依賴就被注入了,我們就能自由使用他們:
public class MainActivity extends AppCompatActivity {
@Inject
ConnectivityManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
((App) getApplication()).getComponent().inject(this);
}
}
總結
當然了,我們可以手動注入依賴,管理所有不同的對象,但 Dagger 消除了很多比如模板這樣的“噪聲”,給我們提供有用的附加品(比如 Singleton
),而僅用 Java 處理將會很糟糕。
原文發布時間為:2017-12-27
本文來自雲棲社區合作夥伴“Linux中國”
最後更新:2017-06-01 11:31:40
上一篇:
為你的 Linux 服務器加把鎖
下一篇:
阿裏雲雲棲社區合作指南
myeclipse9中Jquery.js提示出錯
Java開發牛人十大必備網站
opengl編程學習筆記(四)(紋理映射)(結合nvdia OpenglSDk 的nvimage類)
Sharing Data Among Threads Without Contention
java中short s=s+1和s+=1的區別
Android 對ScrollView滾動監聽,實現美團、大眾點評的購買懸浮效果
自動化所馬佳彬、王威、王亮等研究人員提出不規則卷積神經網絡:可動態提升內核效率
【演講實錄+視頻】走近40+世界級AI專家!第三屆中國人工智能大會資料分享
抵製Android:智能電視打響圈地戰
《R語言遊戲數據分析與挖掘》一2.1 開發環境準備和快速入門