我有使用SQLite数据库(PlaceDbProvider)的课程。它是单音。问题是我有三个使用PlaceDbProvider的活动。什么时候最好为PlaceDbProvider调用destroy方法?我很困惑,因为每个活动都有自己的onDestroy方法。
public class PlaceDbProvider {
private static final String DB_NAME = "com.placesmanager";
private static final String TABLE_NAME = "places";
private static final int DB_VESION = 1;
private static final String KEY_ID = "_id";
private static final int ID_COLUMN = 0;
private static final String KEY_NAME = "name";
private static final int NAME_COLUMN = 1;
private Context context;
private Cursor cursor;
private SQLiteDatabase database;
private DbOpenHelper dbOpenHelper;
private static PlaceDbProvider mInstance = null;
private PlaceDbProvider(Context context) {
this.context = context;
init();
}
public static PlaceDbProvider getInstance(Context context) {
if(mInstance == null) {
mInstance = new PlaceDbProvider(context);
}
return mInstance;
}
public int getCount() {
return cursor.getCount();
}
public Place getItem(int position) {
if (cursor.moveToPosition(position)) {
Place placeOnPositon = new Place();
placeOnPositon.setId(cursor.getLong(ID_COLUMN));
placeOnPositon.setName(cursor.getString(NAME_COLUMN));
return placeOnPositon;
} else {
throw new CursorIndexOutOfBoundsException(
"Cant move cursor to postion");
}
}
public long getItemId(int position) {
if (cursor.moveToPosition(position)) {
return cursor.getLong(ID_COLUMN);
} else {
throw new CursorIndexOutOfBoundsException(
"Cant move cursor to postion");
}
}
public long addItem(Place place) {
ContentValues values = new ContentValues();
values.put(KEY_NAME, place.getName());
long id = database.insert(TABLE_NAME, null, values);
refresh();
return id;
}
public boolean removeItem(Place placeToRemove) {
boolean isDeleted = (database.delete(TABLE_NAME, KEY_NAME + "=?",
new String[] { placeToRemove.getName() })) > 0;
refresh();
return isDeleted;
}
public boolean updateItem(long id, String key,String newValue) {
ContentValues values = new ContentValues();
values.put(key, newValue);
boolean isUpdated = (database.update(TABLE_NAME, values, KEY_ID + "=?",
new String[] {id+""})) > 0;
return isUpdated;
}
public void destroy() {
dbOpenHelper.close();
mInstance = null;
}
private void refresh() {
cursor = getAllEntries();
}
public Cursor getAllEntries() {
String[] columnsToTake = { KEY_ID, KEY_NAME, KEY_LAT, KEY_LNG, KEY_TYPE, KEY_INFO, KEY_OWNER};
return database.query(TABLE_NAME, columnsToTake,
null, null, null, null, KEY_ID);
}
private void init() {
dbOpenHelper = new DbOpenHelper(context, DB_NAME, null, DB_VESION);
try {
database = dbOpenHelper.getWritableDatabase();
} catch (SQLException e) {
Log.e(this.toString(), "Error while getting database");
throw new Error("The end");
}
cursor = getAllEntries();
}
//class for creation, opening and db version control
private static class DbOpenHelper extends SQLiteOpenHelper {
public DbOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
final String CREATE_DB = "CREATE TABLE " + TABLE_NAME + " ("
+ KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ KEY_NAME + " TEXT NOT NULL);";
db.execSQL(CREATE_DB);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
}
答案 0 :(得分:1)
不建议Android使用Singleton模式,因为根据Android的应用生命周期,可能会销毁持有Singleton对象的活动或服务。我建议您扩展应用程序的Application Object并将静态引用部署到数据库。
另一方面,尝试使用ContentProvider进行数据库处理。起初,对于简单的任务来说,它可能听起来太多了,但ContentProvider-ContentResolver组合在使用CursorAdapters和Loaders显示SQLite数据时提供了很大的帮助。如果使用此方法,则不需要数据库初始化或关闭。
希望它有所帮助。
答案 1 :(得分:0)
1)Instanciate PlaceDbProvider与应用程序上下文(context.getApplicationContext())
2)创建应用程序类
3)在你的应用程序类中,在onTerminate()方法中调用(PlaceDbProvider)onDestroy()方法
(请参阅此链接中的其他答案,以创建应用程序类:https://stackoverflow.com/a/13994622/1789730)
答案 2 :(得分:0)
最好像这样实现打开和关闭的方法:
public DbAdapter open() throws SQLException
{
dbHelper = new DbHelper(mCtx);
db = dbOpenHelper.getWritableDatabase();
return this;
}
public void close()
{
dbHelper.close();
}
注意:DbAdapter它是您使用数据库的类。你想在数据库中读取/插入/更新数据之前打开数据库,然后立即关闭,在onDestroy()中不必要。
答案 3 :(得分:0)
我没有看到使用单例模式的特殊问题,只要您正确实现它。确实可以销毁使用单例的Activity或Service,但是如果你可以重新创建单例,这无关紧要。您可以将数据库引用作为单例,只要您记得保持其线程安全。如果引用被破坏,只需重新打开数据库即可。
要关闭它,无论您身在何处,都可以从任何地方调用Database.close(),然后在调用SQLiteDatabase.close()之前检查单例以查看数据库是否已关闭。即使您的应用仍处于打开状态,您也可以决定每次完成数据库时都要关闭数据库。
我同意您等到打开数据库,直到您准备好读/写为止。
请注意,如果在调用SQLiteDatabase.close()之前调用SQLiteDatabase.isOpen(),则尝试关闭它的位置无关紧要。