I have an application which uses a SQL database. This is encapsulated by a SQLiteOpenHelper class. When the splash screen launches, it calls init on a DataProvider class which stores a protected static instance of the SQLiteOpenHelper. init simply calls the constructor of the SQLiteOpenHelper:
public class UKMPGData extends SQLiteOpenHelper
{
public UKMPGData(Context context, String databaseName)
{
super(context, databaseName, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
//create table and set up triggers etc
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
onCreate(db);
}
}
public class UKMPGDataProvider
{
protected static UKMPGData uKMpgData;
public static void init(Context aApplicationContext, String aDatabaseName)
{
uKMpgData = new UKMPGData(applicationContext, databaseName);
}
public static void close()
{
uKMpgData.close();
}
}
I then had two further classes which extended UKMPGDataProvider and therefore had access to uKMpgData. These classes retrieve and store particular types of data from the database. Eg.
public class VehicleDataProvider extends UKMPGDataProvider
{
public static Cursor getVehicles()
{
Cursor cursor = null;
SQLiteDatabase db = uKMpgData.getReadableDatabase();
cursor = db.query(VEHICLE_TABLE_NAME, GET_VEHICLES_FROM_CLAUSE, null, null, null, null, ORDER_BY);
return cursor;
}
//...
}
This all seemed to work fine until I noticed that if the application was running and then forced to the background, if it was left for a number of hours, when the app was brought back to the foreground I would get a null pointer in an Activity class which called getVehicles() (see above). It turns out, uKMpgData was no longer referencing an object.
I understand that Android can kill processes when it is deemed necessary, but don't understand what happened to my app to get the null pointer - if my app's process was killed, then wouldn't a new instance of the app be launched? In other words, a new SplashScreen would initialise the database object and therefore no null pointer exception.
I must be missing something - what state was my app in to have memory reclaimed (the reference to the database object) but to display the last visible activity upon relaunch.
Incidentally, the bug is now fixed. VehicleDataProvider and the other similar class no longer extend the superclass data provider (UKMPGDataProvider), which now holds a private reference to ukMpgData. All methods which touch the database now go through UKMPGDataProvider which will check for null and reinitialise if necessary.
Thanks in advance, Barry