1

I am a little confused how to do this properly. Here is my DatabaseHelper class:

public class DatabaseHelper extends SQLiteOpenHelper {
    private static DatabaseHelper mInstance = null;

    private static final String DB_NAME = "database.db";
    private static final int DB_VERSION = 1; 

    private Context mContext;

    public static DatabaseHelper getInstance(Context context) {

        if (mInstance == null) {
            mInstance = new DatabaseHelper(context.getApplicationContext());
        }
        return mInstance;
    }

    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        mContext = context;
    }

  ...

Assuming this is right, is this the correct way to handle the querying class:

public class DatabaseProcessor {

    private SQLiteDatabase mDatabase;
    private DatabaseHelper mSQLHelper;
    private Context mContext;

    public DatabaseProcessor(Context context) {
        mContext = context;
        mSQLHelper = new DatabaseHelper(mContext);
    }

    private void open() throws SQLException {
        mDatabase = mSQLHelper.getWritableDatabase();
    }

    private void close() {
        mDatabase.close();
    }

    public void insertSomethingIntoDb(String key) {
        ContentValues values = new ContentValues();
        values.put("some_column_name", name);
        open();
        mDatabase.insert("some_table_name", null, values);
        close();
    }
...

And if this is right, how do I properly invoke a db method from somewhere else in the code such as an Activity, Fragment, etc, anywhere.

KaliMa
  • 1,970
  • 6
  • 26
  • 51

1 Answers1

4

You should make the DatabaseHelper constructor private and create instances of this class by using the getInstance method. eg: mSQLHelper = DatamabseHelper.getInstance(context).

To call a method of this class, you can do something like this.

DatabaseHelper.getInstance(context).someFunction(...);

And to use any of the DatabaseProcessor functions, you can do this:

new DatabaseProcessor(context).insertSomethingIntoDb(...);

Keep in mind that this singleton approach has some problems, for starters, it doesn't support multithreading, there is no mechanism in place to assure that if two threads ask for an instance at the same time, only one instance will be created.

Titus
  • 22,031
  • 1
  • 23
  • 33
  • I was thinking of making that constructor private as well (a few examples online had it public so I left it that way just in case), but I am glad to hear this. So let's say you are somewhere in the code, how would you call `insertSomethingIntoDb`? Would I do `DatabaseProcessor db = new DatabaseProcessor(getActivity());` and then `db. insertSomethingIntoDb("some_key");`? – KaliMa Apr 07 '16 at 04:10
  • Since the `getInstance(...)` method is `static`, you can do this `DatabaseHelper.getInstance(context).insertSomethingIntoDb(...)` – Titus Apr 07 '16 at 04:13
  • I can't technically do it that way, the function is in the Processor class – KaliMa Apr 07 '16 at 04:14
  • My app is reasonably simple so I don't know if I need to make it multithreadable. How would I handle that? – KaliMa Apr 07 '16 at 04:18
  • @KaliMa You add support for multithreading by adding some synchronization. The idea is that you create instances of this class only by using `getInstance(...)`, you should never call `new DatabaseHelper(...)` outside the `DatabaseHelper` you won't be able to once you make this class' constructor `private`. – Titus Apr 07 '16 at 04:23
  • But my querying functions are in the Processor class, not the Helper, so would I handle instantiation differently? (see my example above) – KaliMa Apr 07 '16 at 04:24
  • Don't I just need to add "synchronized" to the getInstance() line? `public static synchronized DatabaseHelper getInstance(Context context) {` – KaliMa Apr 07 '16 at 04:36
  • @KaliMa Yes, that will do, you can find more details here: http://stackoverflow.com/questions/11165852/java-singleton-and-synchronization – Titus Apr 07 '16 at 04:43