一个三年Android开发的总结 - 常见数据库问题总结
2016-06-03 08:31
645 查看
Android应用开发离不开对SQLite数据库的操作,一般简单的增删改查,可以直接通过SQLiteDatabase进行,但是只要操作变得频繁,并且随着需求不断增加,你应该考虑使用ORM框架,至少使用SQLiteOpenHelper,结合需要用ContentProvider再封装一层。本文不介绍具体的使用方法,而是列出一些常见的问题,供分析参考。
(1)一个管理数据库连接的辅助类,缓存了已打开的数据库对象,提供了onConfigure onCreate onOpen,getReadableDatabase getWriteableDatabase方法;数据库文件不会直接创建,而是在调用getReadableDatabase或者getWriteableDatabase时才调用onConfigure等方法完成。在这个过程中会比较传入的数据库版本号,从而调用onDowngrade onUpgrade处理升级逻辑,默认的onDowngrade直接抛出异常。同时注意只有在版本号version等于0时,才会调用onCreate方法,所以数据库建表之类的操作可以在此方法中处理。
(2)单个数据库连接 数据库相关操作都将是顺序执行的,因此使用单例的SQLiteOpenHelper,可以基本保证数据库执行的顺序性,避免操作被锁或阻塞
2.ContentProvider
ContentProvider封装后对外提供URI,内部既可以是对数据库的操作,也可以是文件甚至内存的操作。需要注意的是它提供的query delete等操作是在调用的线程中执行的,而非只在主线程。据我在Android4.X时的设备上统计,一般查询操作很快,在1ms左右,而单个的插入删除操作在10ms左右,如果希望界面流畅,在UI线程谨慎的修改数据库。
android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLong(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLong(SQLiteConnection.java:595)
可以出现此问题的一种情况是:创建多个SQLiteOpenHelper实例,一个对应的连接正在写,另一个getWritableDatabase 。 需要避免创建多个实例。
2.android.database.CursorWindowAllocationException
android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed
android.database.CursorWindowAllocationException:
Cursor window allocation of 2048 kb failed. # Open Cursors=22 (# cursors opened
by this proc=22)
或者Could not allocate CursorWindow xxx.db of size 2097152 due to error -9.
一般前者出现open cursors过多,可能是cursor没有close导致,比较稳妥的方法在可能忽略的Java基础知识 - 理解内部类和匿名内部类,异常与异常捕获有介绍。而如果是due to error后面跟-12表示内存消耗过多 具体数值和对应的原因如下所示
是在源码的errno-base.h中可以查到
3.android.database.sqlite.SQLiteDiskIOException
有时碰到android.database.sqlite.SQLiteDiskIOException ,例如
android.database.sqlite.SQLiteDiskIOException: disk I/O error
(code 266)
可根据后面的error code来查找并判断原因,在SQLite Result Codes中查询具体的错误码即可
这个计算的步骤如下:
sqlite3.h中定义了错误码,首先与上0xff得到错误原因,再根据除去最后两个字节的值来判断具体的原因。如266,转成二进制为1 0000 1010,首先与(&)上0xff为1010,也就是SQLITE_IOERR,然后去掉低两个字节,为1,则是SQLITE_IOERR_READ,再到SQLite Result Codes中查询具体的原因
(266) SQLITE_IOERR_READ
The SQLITE_IOERR_READ error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to read from a file on disk. This error might result from a hardware malfunction or because a filesystem came unmounted while the file was open.
转载请注明出处:http://blog.csdn.net/w7849516230,欢迎关注微信公众号“编程阳光”
使用问题
1.SQLiteOpenHelper(1)一个管理数据库连接的辅助类,缓存了已打开的数据库对象,提供了onConfigure onCreate onOpen,getReadableDatabase getWriteableDatabase方法;数据库文件不会直接创建,而是在调用getReadableDatabase或者getWriteableDatabase时才调用onConfigure等方法完成。在这个过程中会比较传入的数据库版本号,从而调用onDowngrade onUpgrade处理升级逻辑,默认的onDowngrade直接抛出异常。同时注意只有在版本号version等于0时,才会调用onCreate方法,所以数据库建表之类的操作可以在此方法中处理。
(2)单个数据库连接 数据库相关操作都将是顺序执行的,因此使用单例的SQLiteOpenHelper,可以基本保证数据库执行的顺序性,避免操作被锁或阻塞
2.ContentProvider
ContentProvider封装后对外提供URI,内部既可以是对数据库的操作,也可以是文件甚至内存的操作。需要注意的是它提供的query delete等操作是在调用的线程中执行的,而非只在主线程。据我在Android4.X时的设备上统计,一般查询操作很快,在1ms左右,而单个的插入删除操作在10ms左右,如果希望界面流畅,在UI线程谨慎的修改数据库。
异常问题
1.数据库被锁异常android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLong(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLong(SQLiteConnection.java:595)
可以出现此问题的一种情况是:创建多个SQLiteOpenHelper实例,一个对应的连接正在写,另一个getWritableDatabase 。 需要避免创建多个实例。
2.android.database.CursorWindowAllocationException
android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed
android.database.CursorWindowAllocationException:
Cursor window allocation of 2048 kb failed. # Open Cursors=22 (# cursors opened
by this proc=22)
或者Could not allocate CursorWindow xxx.db of size 2097152 due to error -9.
一般前者出现open cursors过多,可能是cursor没有close导致,比较稳妥的方法在可能忽略的Java基础知识 - 理解内部类和匿名内部类,异常与异常捕获有介绍。而如果是due to error后面跟-12表示内存消耗过多 具体数值和对应的原因如下所示
#define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ #define ENXIO 6 /* No such device or address */ #define E2BIG 7 /* Argument list too long */ #define ENOEXEC 8 /* Exec format error */ #define EBADF 9 /* Bad file number */ #define ECHILD 10 /* No child processes */ #define EAGAIN 11 /* Try again */ #define ENOMEM 12 /* Out of memory */ #define EACCES 13 /* Permission denied */ #define EFAULT 14 /* Bad address */ #define ENOTBLK 15 /* Block device required */ #define EBUSY 16 /* Device or resource busy */ #define EEXIST 17 /* File exists */ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device */ #define ENOTDIR 20 /* Not a directory */ #define EISDIR 21 /* Is a directory */ #define EINVAL 22 /* Invalid argument */ #define ENFILE 23 /* File table overflow */ #define EMFILE 24 /* Too many open files */ #define ENOTTY 25 /* Not a typewriter */ #define ETXTBSY 26 /* Text file busy */ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device */ #define ESPIPE 29 /* Illegal seek */ #define EROFS 30 /* Read-only file system */ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe */ #define EDOM 33 /* Math argument out of domain of func */ #define ERANGE 34 /* Math result not representable */
是在源码的errno-base.h中可以查到
3.android.database.sqlite.SQLiteDiskIOException
有时碰到android.database.sqlite.SQLiteDiskIOException ,例如
android.database.sqlite.SQLiteDiskIOException: disk I/O error
(code 266)
可根据后面的error code来查找并判断原因,在SQLite Result Codes中查询具体的错误码即可
这个计算的步骤如下:
sqlite3.h中定义了错误码,首先与上0xff得到错误原因,再根据除去最后两个字节的值来判断具体的原因。如266,转成二进制为1 0000 1010,首先与(&)上0xff为1010,也就是SQLITE_IOERR,然后去掉低两个字节,为1,则是SQLITE_IOERR_READ,再到SQLite Result Codes中查询具体的原因
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
(266) SQLITE_IOERR_READ
The SQLITE_IOERR_READ error code is an extended error code for SQLITE_IOERR indicating an I/O error in the VFS layer while trying to read from a file on disk. This error might result from a hardware malfunction or because a filesystem came unmounted while the file was open.
转载请注明出处:http://blog.csdn.net/w7849516230,欢迎关注微信公众号“编程阳光”
相关文章推荐
- facebook的Android调试工具Stetho介绍
- Android 实现简单的分页
- ListView中嵌套ScrollView,ScrollView拦截ListView的Item点击事件的解决办法
- 观察者模式在Android中使用浅析
- Android安卓破解之逆向分析SO常用的IDA分析技巧
- 我学过的android-2 RecyclerView
- Android Studio使用技巧
- 大图片的压缩处理
- Android中如何修改系统时间(应用程序获得系统权限)
- Android Studio 配置以及JNI使用
- Cannot resolve external dependency com.android.support:multidex:1.0.0
- Android SharedPreference
- Android 动态添加布局
- Android 保存到文件
- Android实现倒计时之使用CountDownTimer
- Android LruCache 代码走读
- 开源库soname问题
- 《Android群英传》图像处理之画笔特效处理--Shader篇
- Activity跳转过程中OnActivityForResult()不执行的原因。
- 银行卡输入四位加一空格