Android開發中依賴注入的應用

什麼是依賴注入?

  依賴是指一個對象持有其餘對象的引用。依賴注入則是將這些依賴對象傳遞給被依賴對象,而不是被依賴對象本身建立這些對象。 
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準備好後再改回來。git

  咱們想測試網絡有延遲或錯誤的時候,程序是否會出現異常。這須要經過配置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,咱們須要在兩個不一樣的地方進行注入,所以產生了許多重複代碼。github

  所以,咱們須要一個容器,它知道什麼地方須要注入,注入什麼樣的對象。 

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,則再編寫一個模塊,在初始模塊和依賴對象圖時替換便可。框架

現有的依賴注入性能?

  依賴注入雖能簡化代碼編寫,方便單元測試,但是因爲當前基於反射的依賴注入框架( GuiceRoboGuice)性能並很差。緣由是他們會在程序運行的時候須要掃描代碼中的註解,並須要花費內存映射到內存中。
  這裏推薦使用Dagger是由於它使用了編譯時註解,也就是說在編譯代碼的時候,Dagger就已經完成傳統依賴注入框架在運行時所執行的任務。

何時須要依賴注入?

  當你須要將配置數據注入到一個或多個模塊時。在開發過程當中前端訪問後臺服務器地址會分爲測試服務器和正式服務器,以及各類第三方分享key和ID,依賴注入都是很是好的選擇。
  當須要將同一依賴注入到多個模塊時。如加載圖片以及圖片存儲管理組件(Picasso, Android-Universal-Image-Loader)。
  當須要對同一依賴注入不一樣的實現時。爲方便開發和單元測試,後臺API可有正式API和模擬API,經過依賴注入方便切換環境。
  當同一模塊須要注入不一樣的配置時。

參考資料:

http://square.github.io/dagger/
相關文章
相關標籤/搜索