Android Error处理:java.lang.IllegalStateException: databases already closed
今天导入一个基于Android 2.x版本SDK项目,运行的时候一直出错,错误如下:
11-18 16:58:56.595:E/AndroidRuntime(22991): java.lang.RuntimeException: Unable to start servicexxx.xxxx.service.LocalService@41985638 with Intent {act=xxx.xxx.xxx.APP_SERVICE (has extras) }: java.lang.IllegalStateException:database /data/data/xxx.xxx.xxx/databases/xxx.db (conn# 0) already closed
判断可能是数据库操作部分出了问题,数据库操作部分文件代码DBHelper.java如下:
- package org.yousee.utils;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- /**
- * 存储记录的数据库
- */
- public class DBHelper extends SQLiteOpenHelper {
- private Cursor c = null;
- private static final String CREATE_TAB = "create table "
- + "music(_id integer primary key autoincrement,music_id integer,clicks integer," + "latest text)";
- private static final String TAB_NAME = "list";
- private SQLiteDatabase db = null;
- public DBHelper(Context context, String name, CursorFactory factory,int version) {
- super(context, name, factory, version);
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- this.db = db;
- db.execSQL(CREATE_TAB);
- }
- public void insert(ContentValues values){
- SQLiteDatabase db = this.getWritableDatabase();
- db.insert(TAB_NAME, null, values);
- db.close();//应改为this.close()
- }
- public void update(ContentValues values,int id){
- SQLiteDatabase db = this.getWritableDatabase();
- db.update(TAB_NAME, values, "music_id="+id, null);
- db.close();//应改为this.close()
- }
- public void delete(int id){
- if (db == null){
- db = getWritableDatabase();
- }
- db.delete(TAB_NAME, "music_id=?", new String[]{String.valueOf(id)});
- }
- public Cursor query(int id){
- SQLiteDatabase db = getReadableDatabase();
- c = db.query(TAB_NAME, null, "music_id=?", new String[]{String.valueOf(id)}, null, null, null);
- db.close();//应改为this.close()
- return c;
- }
- public Cursor queryByClicks(){//按点击量查询
- SQLiteDatabase db = getReadableDatabase();
- c = db.query(TAB_NAME, null, null, null, null, null, "clicks desc");
- return c;
- }
- public Cursor queryRecently(){//按时间降序查询
- SQLiteDatabase db = getReadableDatabase();
- c = db.query(TAB_NAME, null, null, null, null, null, "latest desc");
- return c;
- }
- public void close(){
- if (db != null){
- db.close();//应改为this.close()
- db=null;
- }
- if (c!=null){
- c.close();
- c=null;
- }
- }
- @Override
- public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
- }
- }
出错的具体原因为:
如果调用SQLiteDatabase.close()代替SQLiteOpenHelper.close()。那么SQLiteOpenHelper就不知道通过helper获取的DB是否是关闭的(getReadableDatabase或getWritableDatabase)。
总结:
1、SQLiteOpenHelper.close()是异步的,而SQLiteDatabase.close()不是。
2、在使用安卓提供的SQLiteOpenHelper时,通过getReadableDatabase或getWritableDatabase获得的其实是同一个对象,唯一的却别就是如果你的硬盘不足了,那么你就不能在调用getWritableDatabase,只能调用getReadableDatabase。
3、使用Android提供的数据库接口进行数据库操作的时候一定要遵循Andoid的规则。在多线程中要注意,所以养成好的面向对象的习惯,调用helper的close方法关闭数据库。(谁提供的数据,就调用谁的方法来操作数据)
网上还看到有类似的问题:
http://androiddev.orkitra.com/?p=30756
http://stackoverflow.com/questions/6535908/android-sqlite-sqliteopenhelper-error-illegalstateexception-db-already-clo
转自:http://blog.csdn.net/netwalk/article/details/16808897