I read Christian Gruber's post and I started wondering how to use Application-wide Singletons.
In my application I have a class DBHelper
, which main purpose is holding the keys to my database. I have also many (at least two) different DAOs.
Now - I don't see a reason why would my several Activities/classes need more than just a single instance of DAO. What's more, why would a DAO need an instance of DBHelper
just for itself? I'm pretty sure they can share, especially I don't predict a situation when both DAOs would want to perform some operation on my database at the same time. So let's see some classes:
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); } }
example of
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(); } }
Now let's see two examples of dependency consumers
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(); } }
It works, however when I inject(this)
twice, Dagger obviously creates me two instances of DBHelper
as it thinks "One Singleton fon one graph instance". How do I wrap my SomeDataModule
in ApplicationModule
, so I have only one instance of DBHelper
in the entire app? Adding @Singleton
to DBHelper
unfortunately was not enough.