Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLiteOpenHelper synchronization

So I've come up with some idea and I'm wondering if it is realizable.

Let's say I've multiple tables(database models) each of them is represented by some class.I don't wont to use singleton pattern with the open helper so I've created some simple class to provide single instance of the database.My idea is that as long as all tables hold reference to SQLiteDatabase(returned by the open helper) they will all work with the same DB instance and probably won't be needed to synchronized the work with the database since the open helper do this.When the last table finish it's work the GC will collect the open helper (since the last reference will be weak reference) -> finalize() is called and I close the db during this method to prevent any warning from OS. My question is: Is this could work?Will it close automatically the DB and will it leak or throw some exception?

Here is my class:

public class DatabaseHelper {

private static WeakReference<SomeCustomOpenHelper> sDBOpenHelper;

private void notifyDBCreate(SQLiteDatabase db) {
    for (DBTable table : mTables) {
        table.onDBCreate(db);
    }
}

private void notifyDBUpgrade(SQLiteDatabase db) {
    for (DBTable table : mTables) {
        table.onDBUpgrade(db);
    }
}

public SQLiteDatabase getDatabase(boolean readOnly) {
    SomeCustomOpenHelper dbHelper = sDBOpenHelper.get();
    if (dbHelper == null) {
        dbHelper = new SomeCustomOpenHelper(context, name, factory, version, new DatabaseEventsCallback());
        sDBOpenHelper = new WeakReference<SomeCustomOpenHelper>(dbHelper);
    }
    if (readOnly) {
        return dbHelper.getReadableDatabase();
    } else {
        return dbHelper.getWritableDatabase();
    }
}

private class DatabaseEventsCallback implements IDatabaseEventsCallback {

    @Override
    public void onCreate(SQLiteDatabase db) {
        notifyDBCreate(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db) {
         notifyDBUpgrade(db);
    }

}

interface IDatabaseEventsCallback {
    void onCreate(SQLiteDatabase db);

    void onUpgrade(SQLiteDatabase db);
}

private static class SomeCustomOpenHelper extends SQLiteOpenHelper {

    private IDatabaseEventsCallback mCB;

    public SomeCustomOpenHelper(Context context, String name, CursorFactory factory, int version, IDatabaseEventsCallback cb) {
        super(context, name, factory, version);

        mCB = cb;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        mCB.onCreate(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        mCB.onUpgrade(db);
    }

    @Override
    protected void finalize() throws Throwable {
        this.close();
        super.finalize();
    }
}
}
like image 942
Teodor Avatar asked Mar 27 '13 08:03

Teodor


People also ask

What is difference SQLiteOpenHelper and SQLiteDatabase?

If it isn't already exist ofcourse. Difference between SQLiteOpenHelper and SQLiteDatabase close() is that SQLiteOpenHelper just closes inner instance of SQLiteDatabase. And it does it in thread safe way.

What is SQLiteOpenHelper?

SQLiteOpenHelper class is used for database creation and version management. For performing any database operation, you have to provide the implementation of onCreate() and onUpgrade() methods of SQLiteOpenHelper class.

Why do we use class SQLiteOpenHelper?

We can use this class for creating a database and also we can use it for version management. This class provides the onCreate() and onUpgrade() methods for performing any database operation. SQLiteOpenHelper class has two constructors. SQLiteOpenHelper(Context context, String name, SQLiteDatabase.

What is DBHelper Android studio?

public class DBHelper extends java.lang.Object. SmartStore Database Helper Singleton class that provides helpful methods for accessing the database underneath the SmartStore It also caches a number of of things to speed things up (e.g. soup table name, index specs, insert helpers etc)


2 Answers

Did not really know the answer neither, but got interested and looked it up.

The answer is written out properly here; http://blog.foxxtrot.net/2009/01/a-sqliteopenhelper-is-not-a-sqlitetablehelper.html

But basically the core of the info is;

I created three SQLiteOpenHelper classes, one for each table, even though they all referenced only a single database file.

Here is where everything fell apart. Android maintains Versions for databases based on the package it’s associated with, the name of the database, and the version number you provide. The package and name go into decided what the path on the device will be, while the version is stored (somewhere) on the device so that it knows when it needs to call an OpenHelper’s onUpgrade event handler. It turns out that if, in the SQLiteOpenHelper Constructor, it determines that the database already exists, it won’t call your onCreate or onUpgrade methods at all, even if the particular class which is making the call has never been called before.

like image 126
Stefan de Bruijn Avatar answered Oct 06 '22 01:10

Stefan de Bruijn


I've been through the same issue when I was working on a project. I also went crazy on the doubt if the static instance was using enough memory and causing a considerable memory leak.

I'm not sure if creating a weak reference would guarantee that database instance would be collected. However a possible workaround could be : Assigning a null value to static database instance once your all database transaction is done and you've close the database. This might ensure that the database instance no more allocates any memory.

Let me know if this works or if there is a better work-around.

like image 42
Gaurav Arora Avatar answered Oct 06 '22 00:10

Gaurav Arora