1

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

没有 ContentProvider 的 CursorLoader 使用

它是一种在没有内容解析器的情况下使用 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--;
        }
    };

感觉这不是正确的做法。是否有另一种更简洁的方法来仅在需要时关闭/打开数据库?

谢谢,杰森。

4

0 回答 0