繁体   English   中英

实现单例SqliteDatabaseHelper类的正确方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM