使用没有ContentProvider的CursorLoader并避免数据库泄漏

时间:2012-12-30 14:15:36

标签: android sqlite android-loadermanager android-cursorloader connection-leaks

我已经实现了这个问题中的类:

CursorLoader usage without ContentProvider

这是一种在没有内容解析器的情况下使用LoaderManager和CursorLoader的方法。我正在使用它从SQLite数据库加载数据并将其显示在ListFragment中。

我看到的问题是数据库正在泄漏​​。显然这是因为我在完成时没有关闭数据库。

我现在已经开始这样做,但我担心因为可以通过AlarmManager安排的后台任务随时访问数据库。我担心当另一个类需要打开数据库时我可能会关闭数据库。

我的解决方案是计算打开/关闭,只在没有人使用时关闭数据库。像这样:

    public synchronized SQLiteDatabase openDataBase()
{
    try
    {
        mDatabaseUsers++;

        Log.d(TAG, "DatabaseUsers: " + mDatabaseUsers);

        // If already open, return it.
        if (mOpenDatabase != null && mOpenDatabase.isOpen())
            return mOpenDatabase;

        OpenHelper openHelper = new OpenHelper(mContext);
        return openHelper.getWritableDatabase();
    } catch (SQLException e)
    {
        Log.e("MessageDelay", "Error opening database: " + e.toString());

        return null;
    }
}

public synchronized void closeDatabase()
{
    mDatabaseUsers--;

    // If no one is using the database, close it.
    if (mOpenDatabase != null && mDatabaseUsers == 0)
    {
        mOpenDatabase.close();
    }

    Log.d(TAG, "DatabaseUsers: " + mDatabaseUsers);
}

这似乎有效,但它意味着在我的应用程序中添加额外的代码行。此外,我遇到了LoaderManager没有按预期运行的问题,并且它调用了它的重置函数比它的负载更多,所以我不得不把这个修复程序放在:

        return new SimpleCursorLoader(getActivity())
    {
        private int mDBOpens = 0;

        @Override
        public Cursor loadInBackground()
        {
            mDBOpens++;
            return JSQLite.getSingleton(getActivity()).retrieveTextsSent(mMode == 1 ? true : false);
        }

        @Override
        public void reset()
        {
            if (mDBOpens > 0)
            {
                JSQLite.getSingleton(getContext()).closeDatabase();
            }
            super.reset();

            mDBOpens--;
        }
    };

感觉这不是正确的做法。是否有其他更清洁的方法只在需要时关闭/打开数据库?

谢谢,杰森。

0 个答案:

没有答案