1

I have a few singleton sqlite adapters for different tables and queries. In those adapters I find there are a few database-initiation methods and variables that could be put in a base class so that I don't need to write them out over and over again in each adapter. The following is the base class I have made so far with the help of this thread :

Base Class DatabaseHelper

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "postsDatabase";
    private static final int DATABASE_VERSION = 1;
    private static DatabaseHelper sInstance;
    public static String MAIN_TABLE; // will be replaced when instantiated
    private Context context;

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public static synchronized DatabaseHelper getInstance(Context context) {
        // Use the application context, which will ensure that you
        // don't accidentally leak an Activity's context.
        // See this article for more information: http://bit.ly/6LRzfx
        if (sInstance == null) {
            sInstance = new DatabaseHelper(context.getApplicationContext());
        }
        sInstance.context = context;
        return sInstance;
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (oldVersion != newVersion) {
            // Simplest implementation is to drop all old tables and recreate them
            db.execSQL("DROP TABLE IF EXISTS " + MAIN_TABLE);
            onCreate(db);
        }
    }

    // will be replaced when instantiated
    @Override
    public void onCreate(SQLiteDatabase database) {}

    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
    }

}

Used in Adapter:

public class AnimalTableAdapter{

    public AnimalTableAdapter(Context context) {

        dbHelper = new DatabaseHelper(context){

            public static final String MAIN_TABLE = "animal";

            @Override
            public void onCreate(SQLiteDatabase db) {
                CREATE_SEARCH_STRING_TABLE = "//****sql query**** //";
                db.execSQL(CREATE_SEARCH_STRING_TABLE);

            }
        };
        db = dbHelper.getWritableDatabase();
    }
}

However, I don't think the DatabaseHelper base class is a singleton because the constructor is public but when I turn it into a private constructor I can no longer override some of the methods and variables like MAIN_TABLE and onCreate in the animal adapter. Can anyone point me the right way to make a singleton base class?

Community
  • 1
  • 1
RedGiant
  • 4,444
  • 11
  • 59
  • 146

2 Answers2

1

Can anyone point me the right way to make a singleton base class?

A singleton class A that allowed a subclass B would be a contradiction in terms. Any instance of B would also be an A. If an instance of B and an instance of A existed at the same time, then that would violate the "singleton-ness" of A.

Besides, there is no way to implement a subclass of strict (static) singleton class in Java.

A better approach is to move the common code to an abstract superclass of the original singleton class, and write the new singleton classes as subclasses of the abstract class instead or the original singleton class.

I guess you could cobble something together where a singleton's constructor was public and did some gnarly runtime checks to see if it was being invoked via a subclass constructor. But that's a really bad idea ... IMO.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

You are absoulutely right that your DatabaseHelper is not a singleton. You need to make your constructor private to achieve so.

However,your direction seems contradictory to me. Why do you need to anonymously subclass your DatabaseHelper? if you need to query from spcific table with specific query, make a method in the DatabaseHelper and use it from your Adapter.

DatabaseHelper db = DatabaseHelper.getInstance(context);
db.fetchData();
Amit K. Saha
  • 5,871
  • 2
  • 27
  • 35
  • Thanks. I was just thinking of a possibility to not write those methods over and over again in each adapter. – RedGiant Mar 12 '16 at 05:38