SQLiteDatabaseLockedException: d

2017-07-11  本文已影响37人  GinkWang

bug 复现

两个 Fragment 对同一个数据库操作,然后是在这两个 Fragment 切换时出现的这个问题。当时觉得肯定是没有在第一个 Fragment 销毁时及时关闭数据库导致的。原理见此:

文件数据库sqlite,同一时刻允许多个进程/线程读,但同一时刻只允许一个线程写。在操行写操作时,数据库文件被琐定,此时任何其他读/写操作都被阻塞,如果阻塞超过5秒钟(默认是5秒,能过重新编译sqlite可以修改超时时间),就报"database is locked"错误。

但仔细排查后发现,并没有,数据库都已经关闭了,还是会出现这个问题。把数据库的操作写在基类中统一使用也还是不行。没办法了,只好到网上寻求解决方法。

解决方法

网上有几种解决方法,有通过 synchronized 关键字修饰数据库的,也有使用 isDbLockedByOtherThreads 方法判断数据库是否被锁的,还有种方法也是我最终选的解决方法,就是将 SQLiteOpenHelper 写成单例模式的。

操作

1. 在 SQLiteOpenHelper 中定义私有的静态对象

private static DatabaseHelper instance;

2. 为 SQLiteOpenHelper 提供一个单一的入口

保证应用程序使用同一个对象操作数据库,不会因为对象不同而使同步方法失效

public static DatabaseHelper getInstance(Context context){
   if(instance==null)
       instance=new DatabaseHelper(context);
   return instance;
}

3. 数据库中调用

在数据库中通过 getInstance 方法获取 SQLiteOpenHelper 实例

this.mDatabaseHelper = DatabaseHelper.getInstance(pContext);

这样就能保证同一时间内只能有一个 SQLiteOpenHelper 访问 sqlite 数据库,避免同时有两个 SQLiteOpenHelper 访问 sqlite 报错的情况发生。

参考

http://www.voidcn.com/blog/u010002184/article/p-5987070.html

上一篇下一篇

猜你喜欢

热点阅读