在多个Android活动之间共享sqlite数据库

16

两个或多个Android活动可以同时打开一个sqlite3数据库进行写入吗?

我有两个需要向同一个sqlite数据库插入数据的活动。当第二个活动调用SQLiteOpenHelper.getWriteableDatabase()时,会抛出一个IllegalStateException,其中包含消息“SQLiteDatabase created and never closed”。

通过将我的数据库对象设置为单例,我已经能够避免异常,但我认为一定有更好的方法。

谢谢,

John


你可以在写入数据后关闭数据库。 - svens
我也考虑过这个问题,但其中一个活动是使用Cursor适配器填充的ListActivity。我认为关闭数据库会导致适配器的重新查询失败。 - John in MD
@John:如果你使用单例数据库,你在哪里打开和关闭它? - emeraldhieu
需要时我打开数据库,进行操作,然后关闭它。 - John in MD
3个回答

13

在任何时候实际上都不会有超过一个Activity正在运行。解决这个问题的简单方法是在启动第二个Activity之前,第一个Activity关闭它的连接。您可以在onPause()中执行此操作,然后在onResume()中重新打开它。类似这样(非常伪代码):

MyActivity {
    OnResume()
        open connection to database
    OnPause()
        close connection to database
}

这种方式可以确保您不会同时尝试建立多个连接,并且连接始终可用。


3
我一直在思考这种方法是否比让活动使用相同的单例对象更好。我认为是的,因为这种方法在暂停活动时可以保持连接处于正确的状态。使用单例连接会导致问题清理起来比较麻烦。谢谢。 - John in MD
2
我已经在半打应用程序中成功使用了这种模式。如果您遇到问题,那么您一定做了一些有趣的事情。提出问题并发布代码。 - Jeremy Logan
我认为这个伪代码不会起作用,如果你在线程中进行数据库操作。因为你在活动中关闭了与数据库的连接,但是线程仍在运行! - petrnohejl
1
@peno:所以,你是说我的建议解决一个特定的问题,但不能解决完全不同的问题? 想象一下。 - Jeremy Logan
警告:当前的手机可能会出现问题(我们刚刚修复了这个错误——显然有人将此答案用作他们的指南),因为onresume/onpause调用有时会略微重叠(取决于手持设备上正在发生的活动)。最终结果:在最好的情况下是临时损坏,在最坏的情况下是严重崩溃(空DB连接)。我建议使用应用程序范围的DB句柄,而不是这个暂停/恢复的东西。 - Adam
显示剩余4条评论

2

我有多个Activity,每个Activity都会打开自己的数据库连接。在启动其他活动时,我会保持主Activity处于活动状态,并在不再需要它们时调用子活动的finish()方法。

我发现一个问题:当主Activity仍然持有它的DBAdapter时,子Activity可以成功打开连接并查询数据。当子Activity结束时,主Activity会重新查询任何仍然打开的游标,这似乎是自动发生的。

然而,在用户界面上点击一段时间后,我的应用程序会启动和完成多个Activity,最终出现异常:

ERROR/Database(17657): Leak found
ERROR/Database(17657): java.lang.IllegalStateException:
      /data/data/yourpackage/databases/yourdatabase 
      SQLiteDatabase created and never closed
ERROR/Database(17657): at android.database.sqlite.SQLiteDatabase.<init>
     (SQLiteDatabase.java:1694)

异常不是来自当前处于前台的Activity,而是来自一段时间前已经完成的Activity。因此,垃圾回收器正在清理并查找打开的数据库连接。这不会影响应用程序——它继续正常工作,并且前台Activity的所有查询都返回数据。
解决方法很简单,只需在子Activity中关闭连接。onDestroy()事件是正确的处理位置:
@Override    
protected void onDestroy() {        
    super.onDestroy();
    myAdapter.close();
}

自从我在所有子活动中添加了这个代码,我就不再遇到异常了。


0
我会在一个超类中定义数据库,如果所有的活动都扩展了这个类,那么这个超类就是AppCompatActivity;或者在Activity类中定义它,这个类被所有活动继承。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接