標籤:
什麼是依賴注入? 依賴是指一個對象持有其他對象的引用。依賴注入則是將這些依賴對象傳遞給被依賴對象,而不是被依賴對象自己建立這些對象。
public class MyClass{ private AnotherClass mAnotherObject; public MyClass(){ mAnotherObject = new AnotherClass(); }} 通過傳遞對象的方式,所傳遞對象的更改不會影響代碼。
public class MyClass{ private MyInterface mAnotherObject; public MyClass(MyInterface anotherObject){ mAnotherObject = anotherObject; }}
依賴注入可以簡化代碼編寫,並提供一個可適配的環境,方便進行單元測試以及功能模組的配置。
開發中可能會遇到這樣的麻煩。 我們將通過一個例子來理解依賴注入的應用情境:某Android應用需要一個列表來顯示使用者的好友。
public class FriendListFragment{ private FriendListAPI mFriendListAPI; ...... public FriendListFragment(){ mFriendListAPI = new FriendListAPI(); } private void getFriendList(){ mFriendListAPI.getFriendList(new Callback(){ public void onSuccess(List<User> list){ ...... } ...... }); }} public class FriendListAPI{ private OkHttpClient mHttpClient; public FriendListAPI(){ mHttpClient= new OkHttpClient(); //接下來各種Http配置 ...... }}
代碼寫好了,運行程式試試。可是,後台API沒有準備好或者沒有資料怎麼辦?自己添點測試資料試試吧。在FriendListFragment裡面添加一個產生測試資料的方方法buildTestData(),並替換getFriendList()方法。等後台API準備好後再改回來。
我們想測試網路有延遲或錯誤的時候,程式是否會出現異常。這需要通過配置OkHttpClient參數來實現測試情境,於是又要更改FriendListAPI中相關HttpClient配置代碼,測試完後再修改回來。 這樣對代碼進行多次修改,很容易出錯。因此,對於多次使用的模組,我們可以通過注入的方式,將引用傳入需要使用的類中,而不是自己建立。通過編寫兩個API,一個是直接請求後台資料,另一個則只是一些靜態測試資料。需要測試的時候注入可產生測試資料的API,測試完後則切換為正式API。
public class FriendListFragment{ private FriendListAPI mFriendListAPI; ...... public FriendListFragment(FriendListAPI friendListAPI){ mFriendListAPI = friendListAPI; }} public class FriendListAPI{ private OkHttpClient mHttpClient; public FriendListAPI(HttpClient okHttpClient){ mHttpClient= okHttpClient; ...... }}
現在引入一個稍微複雜的情境,更多的Fragment需要使用FriendListAPI,我們需要在兩個不同的地方進行注入,因此產生了許多重複代碼。
因此,我們需要一個容器,它知道什麼地方需要注入,注入什麼樣的對象。
Dagger解決方案。 這裡簡單的展示輕量級依賴注入庫Dagger實現的注入。 首先定義模組:
public class MyModule{ @Provides @Singleton OkHttpClient provideOkHttpClient(){ //這裡可進行各種Http配置 return new OkHttpClient(); } @Provides @Singleton FriendListAPI provideFriendListAPI(){ return newFriendListAPI(); }}
初始化模組以及依賴對象圖。
public class MyApplication extends Application{ private ObjectGraph graph; @Override public void onCreate() { super.onCreate(); graph = ObjectGraph.create(getModules().toArray()); } protected List<Object> getModules() { return Arrays.asList( new MyModule(this)); } public void inject(Object object) { graph.inject(object); }}
最後添加註入點並進行注入。
public abstract class BaseActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((MyApplication) getApplication()).inject(this); }} public class FriendListFragment{ @Inject FriendListAPI mFriendListAPI; ......} public class FriendListAPI{ @Inject OkHttpClient mHttpClient; ......}
如需進行單元測試,或使用可產生測試資料的類比API,則再編寫一個模組,在初始模組和依賴對象圖時替換即可。
現有的依賴注入效能? 依賴注入雖能簡化代碼編寫,方便單元測試,可是由於當前基於反射的依賴注入架構(Guice、RoboGuice)效能並不好。原因是他們會在程式啟動並執行時候需要掃描碼中的註解,並需要花費記憶體映射到記憶體中。 這裡推薦使用Dagger是因為它使用了編譯時間註解,也就是說在編譯代碼的時候,Dagger就已經完成傳統依賴注入架構在運行時所執行的任務。
什麼時候需要依賴注入? 當你需要將配置資料注入到一個或多個模組時。在開發過程中前端訪問後台伺服器位址會分為測試伺服器和正式伺服器,以及各種第三方分享key和ID,依賴注入都是非常好的選擇。 當需要將同一依賴注入到多個模組時。如載入圖片以及圖片儲存管理組件(Picasso, Android-Universal-Image-Loader)。 當需要對同一依賴注入不同的實現時。為方便開發和單元測試,後台API可有正式API和類比API,通過依賴注入方便切換環境。 當同一模組需要注入不同的配置時。參考資料:http://square.github.io/dagger/
Android開發中依賴注入的應用