Search code examples
androidclassthissqliteopenhelper

How do I use SQLiteOpenHelper in a secondary class?


As a new Android programmer, I followed various online examples to create my own class that extends SQLiteOpenHelper...

public class MySQLiteHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION=1;
private static final String DATABASE_NAME="MyDB";

// Main Database Operations
public MySQLiteHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(CREATE_TABLE_A);
    db.execSQL(CREATE_TABLE_B);
}

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
...

public long addRecord(){
    SQLiteDatabase db = this.getWritableDatabase();
....

etc

This works throughout my various activities with no issues. When I want to use it, I call...

    MySQLiteHelper db = new MySQLiteHelper(this);

Then I call the various routines like...

db.addRecord();

Now I have created a secondary class that I need to use throughout the application. In that class, there are some routines that need to process data from the database. Problem is, I can't declare the MySQLiteHelper because of the this which errors out.

Doing some online search I think I understand that I need to get the Context from the application (or the calling activity??), but not sure how to go about doing that with this code.

As I mentioned, I am new to Android... so any code examples would be greatly appreciated.

EDIT

I need to clarify this secondary class as mentioned above. From the aforementioned online examples, the second class is used to "hold" the database record information. It looks something like this...

public class Acct {
    private int     _id;
    private String  _name;
    private String  _phone;

    public Acct() {
    }

    public int get_id(){
        return this._id;
    }
    public void set_id(int id) {
        this._id=id;
    }

    public void set_name(String name){
        this._name=name;
    }
    public String get_name(){
        return this._name;
    }

    public void set_phone(String phone){
        this._name=phone;
    }
    public String get_phone(){
        return this._phone;
    }
    ...

This is typically used with something like this in an activity...

MySQLiteHelper db = new MySQLiteHelper(this);
Acct acct = new Acct();
acct=db.getAccount(searchId);
myEditText.setText(acct.get_name());
...

Where my problem arises, I want to create a routine and code it IN the Acct class so it can be referenced such as...

acct.UpdateData();

This UpdateData routine is where we need to access the db and thus the MySQLiteHelper. It needs to be able, for each account, to go into the database, access some information from another table, do some processing, and store a summary back into this table for easier reference. As mentioned, there is no Context in the Acct class, so this is where I am getting confused.

And to make matters worse, because the Acct class is a 'holding' place for data from the DB, the online examples also use Acct IN the 'MySQLiteHelper' itself during the getAccount routine....

public Acct getAccount(int id){
    SQLiteDatabase db = this.getReadableDatabase();

    String SQL_STRING="SELECT * FROM "+ACCT_TABLE+" WHERE "+ACCT_FLD_ID+" = "+String.valueOf(id);
    Cursor cursor =
            db.rawQuery(SQL_STRING, null);

    Acct acct = new Acct();

    if (cursor!=null) {
        cursor.moveToFirst();

        acct.set_id(cursor.getInt((cursor.getColumnIndex(ACCT_FLD_ID))));

        acct.set_name(cursor.getString(cursor.getColumnIndex(ACCT_FLD_NAME)));
        acct.set_phone(cursor.getString(cursor.getColumnIndex(ACCT_FLD_PHONE)));
                    cursor.close();
    } else {
        acct = null;
    }
    db.close();
    return acct;
}

I hope all this additional helped clarify what I am trying to do for the couple comments and answers posted so far. If you need more information, please ask. I'd like to get this to work, just still not sure how.


Solution

  • Your problem is you need a Context to call the constructor of MySQLiteHelper. You've been successful doing so in an Activity (which is a Context), but now you have some other class (which I will call "Foo") that isn't a Context and doesn't have one.

    A quick solution is to make Foo take a Context in its constructor, and instantiate your MySQLiteHelper like so:

    public class Foo {
        private MyOpenHelper openHelper;
    
        public Foo(Context context) {
            openHelper = new MyOpenHelper(context.getApplicationContext());
        }
    }
    

    If Foo is a singleton, you can do the same thing in whatever method obtains the instance (i.e. force the caller to provide a Context). Every application component either is a Context (Activity, Service) or has a Context (BroadcastReceiver gets one in onReceive(), ContentProvider has getContext()).

    The use of getApplicationContext() here is worth noting: The Application object for your app is always a singleton--only one instance of it will exist for as long as your app is running (this is guaranteed by the OS). Activities can be destroyed, and creating a MySQLiteHelper with one can cause a memory leak. The application Context always exists and so it cannot be leaked.