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