ITKeyword,专注技术干货聚合推荐

注册 | 登录

android - Usage CursorLoader without ContentProvider and avoiding database leaks

itPublisher 分享于

2021腾讯云限时秒杀,爆款1核2G云服务器298元/3年!(领取2860元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1062

2021阿里云最低价产品入口+领取代金券(老用户3折起),
入口地址https://www.aliyun.com/minisite/goods

I have implemented the class found in this question:

Usage CursorLoader without ContentProvider

It is a means of using the LoaderManager and CursorLoader without a content resolver. I am using it to load data from a SQLite database and display it in a ListFragment.

The problem I am seeing is that the database is leaking. Obviously this is because I am not closing the database when I am done.

I have now started to do this, but I am concerned as the database could be accessed at any time by background tasks scheduled with the AlarmManager. I am worried that I might close the database when another class needs it open.

My solution has been to count the opens/closes and only close the database when no one is using it. Like so:

    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);
}

This appears to work, but it has meant adding an extra line of code all over my application. Furthermore I've had trouble with the LoaderManager not behaving as expected and it calls its reset function more than it does its load, so I've had to put this fix in:

        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--;
        }
    };

It feels like this isn't the correct way of doing it. Is there another, cleaner means of closing/opening the database only when needed?

Thanks, Jason.

android sqlite android-loadermanager android-cursorloader connection-leaks
|
  this question
asked Dec 30 '12 at 14:15 Demonofloom 125 2 15 1   "Obviously this is because I am not closing the database when I am done." -- A ContentProvider does not close its database ever, either. –  CommonsWare Dec 30 '12 at 14:19      Thanks, that is interesting to know. –  Demonofloom Dec 30 '12 at 15:40

 | 

Know someone who can answer? Share a link to this question via email, Google+, Twitter, or Facebook.


相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。