2014-12-02 70 views
1

我讀了Christian Gruber的post,我開始想知道如何使用應用程序範圍的單例。
在我的應用程序中,我有一個類DBHelper,其主要目的是持有我的數據庫的關鍵。我也有很多(至少兩個)不同的DAO。
現在 - 我沒有看到爲什麼我的幾個活動/類不僅僅需要一個DAO實例。更重要的是,爲什麼DAO只需要一個DBHelper的實例?我非常肯定他們可以共享,特別是我不預測兩個DAO都希望同時對我的數據庫執行某些操作的情況。讓我們看看一些類:如何在Dagger 1.x中使用Singleton?

  • DBHelper

    @Singleton 
    public class DBHelper extends SQLiteOpenHelper { 
         //some not relevant configuration stuff 
         private Context context; 
    
         @Inject 
         public DBHelper(Context context) { 
          super(context, DATABASE_NAME, null, DATABASE_VERSION); 
          this.context = context; 
         } 
    
        @Override 
        public void onCreate(SQLiteDatabase db) { 
          //db.execSQL, creating tables and stuff 
        } 
    
        @Override 
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
          //dropping tables, creating a new one 
          onCreate(db); 
        } 
    } 
    
  • 例如DAO

    public interface SomeDataDAO { 
         void hai(); 
        } 
    
        public class SomeDataDAOImpl implements SomeDataDAO { 
         private DBHelper dbHelper; 
    
         public SomeDataDAOImpl(DBHelper dbHelper){ 
           this.dbHelper = dbHelper; 
         } 
         @Override 
         public void hai() { 
           SQLiteDatabase database = dbHelper.getWritableDatabase(); 
           dbHelper.doSomeDatabaseStuff() 
         } 
        } 
    
  • SomeDataModule

    @Module(
         injects = { MainActivity.class, SomeServiceImpl.class } 
         ) 
    public class SomeDataModule { 
         private Context appContext; 
    
         @Provides @Singleton 
         public SomeDataDAO provideSomeDataDao(DBHelper dbHelper){ 
          return new SomeDataDAOImpl(dbHelper); 
         } 
    
         @Provides @Singleton 
         public ISomeService provideSomeService(SomeServiceImpl impl){ 
          return impl; 
         } 
    
         @Provides 
         public Context getAppContext(){ 
          return this.appContext; 
         } 
         public SomeDataModule(){ 
          this.appContext = MainActivity.getAppContext(); 
         } 
    } 
    
  • 現在讓我們看看依賴消費者的兩個例子

    public class MainActivity extends ActionBarActivity { 
        @Inject 
        SomeDataDAO someDataDAO; 
        private ObjectGraph objectGraph; 
        @Inject 
        ISomeService someService; 
        private static Context appContext; 
    
    
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         appContext = getApplicationContext(); 
         objectGraph = ObjectGraph.create(SomeDataModule.class); 
         objectGraph.inject(this); 
         someService.doSomeStuff(); 
        } 
    
        public static Context getAppContext() { 
         return appContext; 
        } 
    } 
    


    public class SomeServiceImpl implements ISomeService { 
        private ObjectGraph objectGraph; 
        @Inject public SomeDataDAO someDataDAO; 
    
        public SomeServiceImpl(){ 
         objectGraph = ObjectGraph.create(GraphDataModule.class); 
         objectGraph.inject(this); 
        } 
    
        public void doSomeStuff(){ 
         someDataDAO.hai(); 
        } 
    
    } 
    


它的工作原理,但是當我inject(this)兩次,匕首顯然創造了我的DBHelper兩個實例,因爲它認爲「一個單一的圖形實例」。如何將SomeDataModule包裝在ApplicationModule中,因此我在整個應用程序中只有一個DBHelper實例?不幸的是,將@Singleton添加到DBHelper是不夠的。

+0

如果你必須去單身,爲什麼不使用靜態成員和方法全局類? – 2014-12-02 19:32:34

+0

@KristyWelsh我正在學習Android&Dagger。即使在這種特殊情況下,具有靜態成員和方法的類可能會更好,但我想知道如何通過依賴注入實現我的目標,尤其是當我現在有一個非常簡單的示例時。順便說一句,它甚至是一個適當的設計模式?我不認爲我曾經遇到過這種方法。我遇到了帶有常量,SQL等靜態字段的類,但從未分發DAO。 – spoko 2014-12-02 20:43:13

回答

3

簡單,簡短和答案,解決了一個小的設計缺陷,並與您的問題是以下內容。而不是創建一個新的ObjectGraphSomeServiceImpl中注入SomeDataDAO實例,您確實應該將SomeDataDAO傳遞給您的構造函數。這實際上就是依賴注入通常意味着:使用某些對象的構造函數注入其依賴關係:

public class SomeServiceImpl implements ISomeService { 

    private final SomeDataDAO someDataDAO; 

    @Inject 
    public SomeServiceImpl(SomeDataDAO someDataDAO){ 
     this.someDataDAO = someDataDAO; 
    } 

    public void doSomeStuff(){ 
     someDataDAO.hai(); 
    } 
} 

現在,這是神奇的發生。注意構造函數的註釋@Inject?它告訴Dagger在請求SomeServiceImpl的實例時使用此構造函數,並且查詢ObjectGraph的參數。

所以,當你有低於這個Provides方法,匕首已經知道SomeServiceImpl取決於SomeDataDAO,並使用你的provideSomeDataDAO方法來提供實例。而且,嘿,這是一個單身人士,所以這與ObjectGraph檢索的SomeDataDAO的任何其他實例完全相同!

@Provides @Singleton 
    public ISomeService provideSomeService(SomeServiceImpl impl){ 
     return impl; 
    } 

其實,你不希望使用​​過於頻繁,你真的想使用上述方法。然而,有些情況下,你不會決定什麼構造函數看起來像。在Android中,例如,這些是ActivityView等等。對於這些特殊情況,創建了ObjectGraph.inject,所以仍然可以使用Dagger注入依賴關係。

最後的注意:在SomeServiceImpl我做了someDataDAOprivate。正如你可能知道的那樣,這是處理實例字段的首選方式,並且使用可注入構造函數來啓用它。

原來這個答案不是那麼短都:O)

+0

[這](https://github.com/square/dagger/tree/master/examples/android-activity-graphs)是一個如何使用多個模塊的例子。 – nhaarman 2014-12-02 21:44:57