问题
anyone can teach me when i should to close a sqlite open bbdd and a cursor?
I have this class
public class DataBaseHelper
{
Context context;
private static final String DATABASE_NAME="lugaresbbdd";
private SQLiteDatabase db; // Referencia al manager.
private final int DB_VERSION = 1; // version
CustomSQLiteOpenHelper helper;
// Nombres para las tablas y campos
private final String TABLE_NAME = "lugares";
private final String TABLE_ROW_ID = "_id";
static String CNOMBRE = "nombre";
private final String CDESC = "descripcion";
private final String CLAT = "latitud";
private final String CLONG="longitud";
static String CFOTO="foto";
public DataBaseHelper(Context context)
{
this.context = context;
//Crea o abre la BBDDD
CustomSQLiteOpenHelper helper = new CustomSQLiteOpenHelper(context);
db = helper.getWritableDatabase();
}
public Cursor getNombres(){
//CustomSQLiteOpenHelper helper = new CustomSQLiteOpenHelper(context);
//db = helper.getWritableDatabase();
Cursor respuesta = db.rawQuery("select "+TABLE_ROW_ID+","+CNOMBRE+" from "+TABLE_NAME, null);
return respuesta;
}
And this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listatab);
context = getBaseContext();
//Creamos la instancia de DataBaseHelper, un cursor y aplicamos el metodo getNombres al cursor y llamamos al metodo encargado de gestioanr ese cursor
ayudabbdd = new DataBaseHelper(this);
nombresC = (Cursor) ayudabbdd.getNombres();
startManagingCursor(nombresC);
nombresC.moveToFirst();
//Para crear un simpleCursorAdapter necesitamos
//Contexto this
//Layour donde se mostrara el resultado, generalmente un textview
//Cursor
//Cual sera el campo que recibiremos de la BBDD
//Donde tenemos que poner esa informacion, generalmente el ID correspondiente al textvies del layour del segundo parametro
String[] deNombre = new String[]{DataBaseHelper.CNOMBRE};
int[] aNombre = new int[]{R.id.nombreLugar};
lugaresNombre = new SimpleCursorAdapter(this, R.layout.entrada_lista, nombresC, deNombre, aNombre);
setListAdapter(lugaresNombre);
listaview= getListView();
listaview.setOnItemClickListener(this);
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Intent intent = new Intent(listatab.this, mostrarLugar.class);
startManagingCursor(nombresC);
String nombreClicks= nombresC.getString(nombresC.getColumnIndex("nombre"));
intent.putExtra("nombre",nombreClicks);
startActivity(intent);
nombresC.close();
}
@Override
public void onDestroy()
{
nombresC.close();
ayudabbdd.close();
super.onDestroy();
}
@Override
protected void onPause() {
nombresC.close();
ayudabbdd.close();
super.onPause();
}
In the second class if i click on a item log cat said me:
android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
But if i close the cursor in onCreate method, don't populate me the list view, then, when i must to close the cursor nombresC?
回答1:
I don't know precisely, but for my opinion I think that you have to open database in onResume method of your activity and close it onPause. As for Cursors you should close them after you do not need them. For instance, if your database helper class returns cursor as a result of query then you should close it when you process all rows of the cursor.
I advice you to consider Notepad example. There are some very good tips how to work with databases in Android.
UPDATE: Here is an example how I usually populate my list in an activity:
public class AcWords extends Activity {
/** Called when the activity is first created. */
DbWordsAdapter dbWordsAdapter;
ListView vw;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_words);
vw = (ListView) findViewById(R.id.ac_words_lv_words);
dbWordsAdapter = new DbWordsAdapter(this);
dbWordsAdapter.open();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
SimpleCursorAdapter adtWord = new SimpleCursorAdapter(this, R.layout.ac_words_vw_wordrow,
dbWordsAdapter.getWordsOrderedByAlph(),
new String[] { DbWordsAdapter.C_WORD, DbWordsAdapter.C_EXPLANATION },
new int[] { R.id.ac_words_vw_wordrow_tv_word, R.id.ac_words_vw_wordrow_tv_explanation });
vw.setAdapter(adtWord);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
dbWordsAdapter.close();
}
}
And this is my helper class:
public class DbWordsAdapter {
private static final String TAG = DbWordsHelper.class.getSimpleName();
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static DbWordsHelper dbWordsHelper;
private Context context;
private SQLiteDatabase mDb;
// database constants
private static final String DB_NAME = "words.db";
private static final int DB_VERSION = 1;
private static final String TABLE_WORDS = "words";
// database columns names
public static final String C_ID = BaseColumns._ID;
public static final String C_WORD = "word";
public static final String C_EXPLANATION = "explanation";
public static final String C_CREATION_DATE = "creation_date";
//Sql Statements
static final String CREATE_TABLE_WORDS = "create table " + TABLE_WORDS
+ "(" + C_ID + " integer primary key autoincrement, " + C_WORD
+ " text not null, " + C_EXPLANATION + " text, "
+ C_CREATION_DATE + " date not null)";
static final String DROP_TABLE_WORDS = "drop table if exists "
+ TABLE_WORDS;
static final String[] ALL_COLUMNS = { C_ID, C_WORD, C_EXPLANATION,
C_CREATION_DATE };
static final String ORDER_BY_DATE = C_CREATION_DATE + " desc";
static final String ORDER_BY_ALPH = C_WORD + " asc";
static final String ORDER_BY_RANDOM = "random() limit 1";
/*
* Inner class that manages database creation and management
*/
private static class DbWordsHelper extends SQLiteOpenHelper {
private DbWordsHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "SqlCreate Statement: "
+ CREATE_TABLE_WORDS);
try {
db.execSQL(CREATE_TABLE_WORDS);
} catch (SQLException e) {
Log.e(TAG, "Error while creating database" + TABLE_WORDS, e);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Here in the future should be method that change the schema of the
// database. Now we just delete
try {
db.execSQL(DROP_TABLE_WORDS);
} catch (SQLException e) {
Log.e(TAG, "Error while updating database" + TABLE_WORDS, e);
}
onCreate(db);
}
}
public DbWordsAdapter(Context context) {
this.context = context;
}
public DbWordsAdapter open () {
if (dbWordsHelper == null) {
dbWordsHelper = new DbWordsHelper(context);
}
mDb = dbWordsHelper.getWritableDatabase();
return this;
}
public void close () {
dbWordsHelper.close();
dbWordsHelper = null;
}
public Cursor getWordDetails(long rowId) {
Log.d(TAG, "getWordDetails method");
Cursor mCursor = mDb.query(TABLE_WORDS, ALL_COLUMNS, C_ID + "=?",
new String[] { String.valueOf(rowId) }, null, null, null);
return mCursor;
}
}
You can use it as a template for your case.
来源:https://stackoverflow.com/questions/8756601/when-close-the-bbdd-and-when-close-the-cursor