LATEST:查看底部的代码,查看我的破解方案。
原文:我遵循了一些教程和例子,并去做了我自己的数据库。问题是,当我将数据库下载到手机时,它应该被读取并填充一个旋转器。我发现下载的数据库是完整的,但是当它被dbhelper读取时,它以某种方式被重写为一个空白表。我不明白为什么。
EDIT1:对不起,我应该说得更清楚些。数据库来自服务器。直接下载到/data/data/project/databases/。文件下载后我就是在那里检查的。它很好,直到我调用'DbAdapter mDbHelper = new DbAdapter(context);’之后,Android元数据表、名称表和sqlite表仍然在数据库中,列有名称,但没有条目,所以表本质上是空白的。
编辑2:(抱歉这么久)
我在下面注释了:
c = initSpinner(c);
是我写的一个方法,以防游标返回!moveToFirst()。在此方法中,创建数据库并将"add name"插入到表中。
然后我稍微玩了一下这个应用程序,这是我发现的:
当我第一次在我的设备上打开应用程序时,在一个全新的安装中,旋转器显示默认的"添加名称"。所以我添加了一个名字。我重新打开应用程序,我输入的名字就在那里,还有"添加名字"…清除所有数据并卸载后进入模拟器。打开应用程序,只有"添加一个名字"在那里。退出并重新打开,旋转器显示"添加名称"和我在手机上输入的名称……所以我在模拟器上添加了一个名称,回到我的手机,关闭并重新打开应用程序,现在有2个名称和"添加名称"…
总结:它的工作原理,但我必须重新打开应用程序后,初始安装读取数据库并正确填充旋转器。为什么?
EDIT3(最新):参见最后的代码破解解决方案…
下面是填充旋转控件的代码。
private void fillSpinner(){
DbAdapter mDbHelper = new DbAdapter(context);
mDbHelper.open("names");
Cursor c = mDbHelper.fetchAllRows();
ArrayList<String> a = new ArrayList<String>();
if ( c.getPosition() != 0 && c.moveToFirst() == (false) ){
// c = initSpinner(c); //commented out to prevent creating a new //database.
}
是DbAdapter的代码。
public class DbAdapter {
// Database fields
public static final String KEY_ROWID = "_id";
public static final String KEY_NAME = "name";
static final String DATABASE_TABLE = "names";
private Context context;
private SQLiteDatabase database;
private DbHelper dbHelper;
public DbAdapter(Context ctx) {
context = ctx;
}
public SQLiteDatabase openToRead() throws SQLException {
dbHelper = new DbHelper(context);
database = dbHelper.getReadableDatabase();
return database;
}
public SQLiteDatabase open(String dbname) throws SQLException {
dbHelper = new DbHelper(context);
database = dbHelper.getWritableDatabase();
return database;
}
public void close() {
dbHelper.close();
}
//
/**
* Create a new todo If the todo is successfully created return the new
* rowId for that note, otherwise return a -1 to indicate failure.
*/
public long createRow(String name) {
ContentValues initialValues = createContentValues(name);
return database.insert(DATABASE_TABLE, null, initialValues);
}
public long createRowWithAL(ArrayList<String> values){
ContentValues v = ArrayListToContentValues(values);
return database.insert(DATABASE_TABLE, null, v);
}
private ContentValues ArrayListToContentValues(ArrayList<String> parcel){
ContentValues values = new ContentValues();
// values.put(KEY_ROWID, _id);
values.put(KEY_NAME, parcel.get(0));
return values;
}
/**
* Update the todo
*/
public boolean updateRows(long rowId,
String name) {
ContentValues updateValues = createContentValues(
name);
return database.update(DATABASE_TABLE, updateValues, KEY_ROWID + "="
+ rowId, null) > 0;
}
/**
* Deletes todo
*/
public boolean deleteRow(long rowId) {
return database.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
/**
* Return a Cursor over the list of all todo in the database
*
* @return Cursor over all notes
*/
public Cursor fetchAllRows() {
return database.query(DATABASE_TABLE, null, null, null, null,
null, null);
}
/**
* Return a Cursor positioned at the defined todo
*/
public Cursor fetchRow(long rowId) throws SQLException {
Cursor mCursor = database.query(true, DATABASE_TABLE, new String[] {
KEY_ROWID ,KEY_NAME},
KEY_ROWID + "=" + rowId, null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
private ContentValues createContentValues(String name){
ContentValues values = new ContentValues();
values.put(KEY_NAME, name);
return values;
}
//returns (an) entire column(s), all rows
public Cursor fetchColumns(String[] colnames) {
Cursor mCursor = database.query(DATABASE_TABLE, colnames, null,
null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
}
下面是DbHelper的代码。
public class DbHelper extends SQLiteOpenHelper {
Context context;
private static final String DATABASE_NAME = "names";
private static final int DATABASE_VERSION = 1;
// Database creation sql statement
private static final String DATABASE_CREATE = "create table if not exists "+DATABASE_NAME+" (_id integer primary key autoincrement, " +
"name text not null);";
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Method is called during creation of the database
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE);
}
// Method is called during an upgrade of the database, e.g. if you increase
// the database version
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion,
int newVersion) {
Log.w(DbHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
database.execSQL("DROP TABLE IF EXISTS names");
onCreate(database);
}}
——黑客代码:
private void fillSpinner(){
DbAdapter mDbHelper = new DbAdapter(context);
mDbHelper.open("name");
mDbHelper.createRow("Add Name"); //added this
mDbHelper.close(); //added this
downloadFile(); //added this
mDbHelper.open("names");
Cursor c = mDbHelper.fetchAllRows();
ArrayList<String> a = new ArrayList<String>();
if ( c.getPosition() != 0 && c.moveToFirst() == (false) ){
c.close();
mDbHelper.createRow("Add Name");
c = mDbHelper.fetchColumns(new String[] {"_id","name"});
}
你说的"当我把数据库下载到手机上"是什么意思?我猜你的资产里包括了你的数据库吧?如果是这样的话……
SQLiteOpenHelper
在应用程序私有内部存储中查找数据库。它将找不到数据库,因此将在内部存储中创建一个新数据库。这就是它将从中读取的数据库。
我想到的几个选项:
- 在
DbHelper
onCreate中创建并填充数据库(而不是像现在这样创建一个空数据库)。如果它是一个简单的小数据库,我会这样做。 - 从资产复制到内部存储。例如http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
这是一个hack/workaround我发现,但为什么它的工作?
private void fillSpinner(){
DbAdapter mDbHelper = new DbAdapter(context);
mDbHelper.open("name");
mDbHelper.createRow("Add Name"); //added this
mDbHelper.close(); //added this
downloadFile(); //added this
mDbHelper.open("names");
Cursor c = mDbHelper.fetchAllRows();
ArrayList<String> a = new ArrayList<String>();
if ( c.getPosition() != 0 && c.moveToFirst() == (false) ){
c.close();
mDbHelper.createRow("Add Name");
c = mDbHelper.fetchColumns(new String[] {"_id","name"});
}