0

我有使用 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);
    }
}

}

4

4 回答 4

1

单例模式不推荐用于 Android,因为根据 Android 的应用程序生命周期,持有单例对象的活动或服务可能会被销毁。我建议您扩展应用程序的应用程序对象并部署对数据库的静态引用。

另一方面,尝试使用 ContentProvider 进行数据库处理。起初,对于简单的任务来说听起来工作量太大,但是 ContentProvider-ContentResolver 组合在使用 CursorAdapters 和 Loaders 显示 SQLite 数据时提供了很大的帮助。如果使用此方法,则不需要数据库初始化或关闭。

希望能帮助到你。

于 2012-12-21T22:54:34.323 回答
0

1) 使用应用程序上下文实例化 PlaceDbProvider (context.getApplicationContext() )

2)创建您的应用程序类

3)在您的应用程序类中,在 onTerminate() 方法中,调用 (PlaceDbProvider) onDestroy() 方法

(有关创建应用程序类的信息,请参阅我在此链接上的其他答案:https ://stackoverflow.com/a/13994622/1789730 )

于 2012-12-21T22:46:54.907 回答
0

最好像这样实现方法打开和关闭:

public DbAdapter open() throws SQLException
{
    dbHelper = new DbHelper(mCtx);
    db = dbOpenHelper.getWritableDatabase();
    return this;
}

public void close()
{
    dbHelper.close();
}

注意: DbAdapter 它是您使用数据库的类。你应该在你想从数据库中读取/插入/更新数据之前打开你的数据库,然后立即关闭,这在 onDestroy() 中是不必要的。

于 2012-12-21T22:56:28.117 回答
0

只要您正确实现它,我看不出使用单例模式有什么特别的问题。确实,使用单例的 Activity 或服务可能会被销毁,但是如果您可以重新创建单例,这并不重要。只要您记得保持线程安全,就可以将数据库引用作为单例。如果引用被破坏,只需重新打开数据库。

无论您身在何处都可以关闭它,您可以从任何您想要的地方调用 Database.close(),然后在调用 SQLiteDatabase.close() 之前签入单例以查看数据库是否已关闭。您可能会决定在每次完成数据库时都关闭它,即使您的应用程序仍处于打开状态。

我同意您等待打开数据库,直到您准备好读/写。

请注意,如果在调用 SQLiteDatabase.close() 之前调用 SQLiteDatabase.isOpen(),则尝试关闭它的位置无关紧要。

于 2012-12-21T23:18:02.463 回答