[英]Proper way of implementing a singleton SqliteDatabaseHelper class
我当前正在实现一个databasehalper类,该类可以从各个线程进行访问,因此基本上是单例并按如下方式访问:
public class HistoryDatabaseHelper extends SQLiteOpenHelper{
private static HistoryDatabaseHelper mInstance=null;
public static HistoryDatabaseHelper getInstance(Context context){
if(mInstance==null)
mInstance=new HistoryDatabaseHelper(context.getApplicationContext());
return mInstance;
}
因此,没有公共构造函数,这是访问助手的唯一方法。
现在我的问题是,我每次尝试执行任何操作时都应该打开数据库。 例如,考虑以下helper类的menmber函数:
public void deleteContact(String staticUrl) {
SQLiteDatabase db = this.getWritableDatabase(); // does this open a new connection each time?
// and invade the whole purpose of
//creating singleton helper
db.delete(TABLE_DOWNLOAD_HISTORY, KEY_STATIC_URL + " = ?",
new String[] { staticUrl });
db.close();
}
那么这是正确的方法还是我应该像这样打开数据库:
public static HistoryDatabaseHelper getInstance(Context context){
if(mInstance==null){
mInstance=new HistoryDatabaseHelper(context.getApplicationContext());
mInstance.open(); // here
}
return mInstance;
}
如果是这样,那我们应该在哪里关闭数据库?
停止! 等待! 冻结!
“我目前正在实现一个databasehalper类,该类可以从各个线程进行访问,因此它基本上将是单例的,并且可以这样访问:”
您说您的HistoryDatabaseHelper将通过各种线程进行访问,而您忘记了同步getInstance方法? 您的线程在离开家之前要穿上跑鞋,因为它们肯定适合比赛条件。 如果您希望线程的行为像大人一样,则需要同步getInstance方法。 或者,您可以在声明本身期间实例化mInstance实例变量,而无需同步getInstance或检查getInstance内部是否已初始化mInstance。
接下来是HistoryDatabasrHelper构造函数。 您需要显式声明一个私有的HistoryDatabaseHelper构造函数,因为否则编译器会将公共构造函数放置在您的类中。 不这样做,就像是让邻居的窃贼从您手中窃取,而不是将其移交给警察。
最后但并非最不重要的是getInstance方法的Context参数。 删除此参数。 让您的HistoryDatabasrHelper具有一个Context实例变量,并在您的私有构造函数中对其进行初始化,假设Context不会从一个实例更改为另一个实例。
那你应该有一个单例数据库连接吗? 我个人认为,如果您有一个单例数据库连接池而不是一个单例数据库连接,那将是一个更好的主意。 Google搜索将为您提供许多很好的库,用于在那里进行连接池。
如果HistoryDatabaseHelper是线程安全的,则只能是单例。 调用者必须传递参数以获取单例的事实应该是一个大的危险信号,因为这意味着单例的状态与此参数有关。
从线程的角度来看,最安全的事情是使该类不是单例,只需根据需要创建一个新类。 如果事实证明这使您的应用程序变慢,请对其进行基准测试并开发解决方案,可能使用诸如c3p0等的连接池。
如果确定HistoryDatabaseHelper是线程安全的,则在类中初始化单例,并且不需要任何参数即可获取单例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.