最佳的关闭数据库连接的位置

66

我寻找了很久关于我的问题的答案,但是我没有得到我所需要的。 我有一个带有ListView的应用程序和一个表单,可以向数据库添加新记录。 所以不需要进行太多查询。

如何处理与数据库的连接? 在得到所需内容后关闭它还是一直保持打开状态直到应用程序关闭? 性能和电池寿命最好的方法是什么?


2
这里有一个很好的解释...https://dev59.com/4GYr5IYBdhLWcg3wB16h#25379071 - Zar E Ahmer
3个回答

133
根据一位Google工程师(Dianne Hackborn)的这篇文章,保持数据库连接开放没有问题:

Android做出了一个故意的设计决策,虽然看起来令人惊讶, 但只是放弃了应用程序干净退出的整个想法, 而是让内核清理它们的资源。毕竟, 内核无论如何都需要能够这样做。鉴于这种设计, 在整个进程生命周期中保持 任何 东西打开并且从未关闭它不是泄漏。 它将在进程被清理时被清理。

因此,为了简单起见,可以扩展Application类以提供单个定义良好的代码入口点,并在其onCreate()中打开数据库连接。 将DB连接存储为Application中的一个字段,并提供一个访问器方法来使连接对您的代码的其余部分可用。
然后,不要担心关闭它。

6
任何替代方案如何比一种始终有效且极其简单的东西“更好”? - Graham Borland
3
保持数据库连接处于打开状态似乎是一种不好的做法,即使说它会在应用程序关闭后被关闭,我没有在Android文档中找到这种行为的描述,如果有的话,这总是意味着更多的工作量对于Android(保持连接和关闭它们)。此外,如果两个应用程序并排工作(它们可以同时作为服务和活动运行),并且它们都保持连接处于打开状态,那会发生什么?当然,这种情况并不常见,这就是我支持这种解决方案的原因。 - Jānis Gruzis
4
@JānisGruzis 这是基于 Linux 内核的 Android 系统的一个功能;当一个进程(例如您的应用程序)终止时,操作系统将清除所有未被保留(例如未存储到磁盘)的内容:所有内存将被回收,所有句柄将被关闭等。话虽如此,我更喜欢明确地表达生命周期... - user166390
6
考虑到*getWritableDatabase()*的文档:“创建并/或打开一个用于读写的数据库...成功打开后,数据库会被缓存,因此每次需要写入数据库时都可以调用此方法。(确保在不再需要数据库时调用close()方法。)”,这似乎有点奇怪。 - Mahm00d
7
@Mahm00d,当你确定你的应用程序被操作系统关闭时,就完全不需要数据库了。所以让操作系统为你处理它。 :) - Graham Borland
显示剩余6条评论

5

通常情况下,我会在打开连接的Activity的onDestroy()函数中关闭连接。我会在使用游标的函数中关闭数据库中的游标。

public MyActivity extends Activity{
    private myDatabase mDatabase; // myDatabase extends SQLiteOpenHelper
    private Cursor mCursor;

    public MyActivity(Context context){
        super(context);
        initMemberVariables();
    }

    public ElementButton(Context context, AttributeSet attrS){
    super(context, attrS);
        initMemberVariables();
    }

    public ElementButton(Context context, AttributeSet attrS, int defStyle){
        super(context, attrS, defStyle);
        initMemberVariables();
    }

    private void initMemberVariables(){
        mDatabase = new PSEdb(this.getContext());
    }

    private void getData(){
        mCursor = mDatabase.MyGetterFunction();
        while(mCursor.moveToNext()){
            try{
                // populate your data
            }catch(CursorIndexOutOfBoundsException ex){
                // handle the exception
            }
        }
        mCursor.close();
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        mDatabase.close();
    }
}

4

连接数据库是一项昂贵的操作。如果连接不会短缺,且数据库在本地,我会保持连接处于打开状态,而不是为每个写入操作重新建立连接。这通常适用于需要扩展以容纳大量并发用户的客户端-服务器应用程序。


1
是的,我发现打开连接可能会很昂贵。所以如果我理解你的意思,我应该保持连接开放。但是如果用户回到主屏幕怎么办?我应该在onPause()中关闭它,在onResume()中重新打开吗?我该如何在Intents之间传递它? - Fixus
@Fixus 我认为,但我可能错了,这个想法是使用单例模式。现在,你可以通过使用全局变量来实现 -- 这对测试来说很困难。或者,你可以使用依赖注入库,例如 Hilt 和 Dagger 2,以便它可以为你管理整个过程。DI 通常会带有支持包来帮助进行模拟和测试。 - adonese

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