onCreate()方法不会被getWritableDatabase()调用

11

我正在我的 Android 应用程序中编写数据库,但是我的表未被创建。我在 onCreate 方法和 getWriteableDatabase、getWritableDatabase 中添加了断点,并且已经调用了 getWriteableDatabase 和 getWritableDatabase,但 onCreate 没有被调用。

package com.fslade.app;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "applicationdata";
    private static final int DATABASE_VERSION = 1;
    public static final String DATABASE_TABLE = "peopleT";

    // Database creation sql statement
    private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " (_id integer primary key autoincrement, "
            + "company_name text not null, name text not null, city text not null, vertical text not null, title text not null, email text not null, bio text not null, photo text not null, status text not null);";

    public DatabaseHelper(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(DatabaseHelper.class.getName(),
                "Upgrading database from version " + oldVersion + " to "
                        + newVersion + ", which will destroy all old data");
        database.execSQL("DROP TABLE IF EXISTS todo");
        onCreate(database);
    }
}

在我的数据库帮助类中,我调用了getWritableDatabase()方法:

package com.fslade.app;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

public class ContentStorageHelper {
    public static final String KEY_ID = "_id";
    public static final String KEY_COMPANY_NAME = "company_name";
    public static final String KEY_PERSON_NAME = "name";
    public static final String KEY_CITY = "city";
    public static final String KEY_VERTICAL = "vertical";
    public static final String KEY_TITLE = "title";
    public static final String KEY_EMAIL = "email";
    public static final String KEY_BIO = "bio";
    public static final String KEY_PHOTO = "photo";
    public static final String KEY_STATUS = "status";

    private static final String[] COLUMNS = { KEY_ID, KEY_COMPANY_NAME,
            KEY_PERSON_NAME, KEY_CITY, KEY_VERTICAL, KEY_TITLE, KEY_EMAIL,
            KEY_BIO, KEY_PHOTO, KEY_STATUS };

    private Context context;
    private SQLiteDatabase database;
    private DatabaseHelper dbHelper;

    public ContentStorageHelper(Context context) {
        this.context = context;
    }

    public ContentStorageHelper open() throws SQLException {
        dbHelper = new DatabaseHelper(context);
        database = dbHelper.getWritableDatabase();
        // dbHelper.onCreate(database);
// I added this onCreate() to see if it helped, but when I ran it
// it said that the database had already been created
        return this;
    }

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

/**
 * Create a new person If the person is successfully created return the new
 * rowId for that person, otherwise return a -1 to indicate failure.
 */
public long createPerson(String company_name, String name, String city,
        String vertical, String title, String email, String bio,
        String photo, String status) {
    ContentValues initialValues = createContentValues(company_name, name,
            city, vertical, title, email, bio, photo, status);

    return database.insert(DatabaseHelper.DATABASE_TABLE, null,
            initialValues);
}

/**
 * Return a Cursor over the list of all people in the database
 * 
 * @return Cursor over all notes
 */
public Cursor fetchPeopleByVertical(String vertical) {
    String selection = KEY_VERTICAL+"="+vertical;
        Cursor result = database.query(DatabaseHelper.DATABASE_TABLE, COLUMNS,
                selection, null, null, null, null);
        return result;
    }

    private ContentValues createContentValues(String company_name, String name,
            String city, String vertical, String title, String email,
            String bio, String photo, String status) {
        ContentValues values = new ContentValues();
        values.put(KEY_COMPANY_NAME, company_name);
        values.put(KEY_PERSON_NAME, name);
        values.put(KEY_CITY, city);
        values.put(KEY_VERTICAL, vertical);
        values.put(KEY_TITLE, title);
        values.put(KEY_EMAIL, email);
        values.put(KEY_BIO, bio);
        values.put(KEY_PHOTO, photo);
        values.put(KEY_STATUS, status);
        System.out.print("test: " + status);
        return values;
    }
}

5个回答

19

创建只会发生一次(这就是整个数据库助手的意义)。

您检查过数据库是否已经创建了吗? 它位于 /data/data/your.package.name/databases/dbname 中。

如果在 Android 应用程序设置中清除应用程序数据,则应该再次调用您的 onCreate...


这正是问题所在。我之前已经在开发中运行了onCreate,但使用了格式不正确的SQL创建命令。我该如何清除Eclipse中的应用程序设置? - Francesca
我不明白为什么你想在Eclipse中进行操作,因为这只是你的代码而已,并没有任何改变。如果你想从设备中删除现有的应用程序数据,请前往“Android设置 > 应用程序 > 管理应用程序 > 你的应用程序 > 删除数据”(如果名称不匹配,抱歉,我的菜单是德语)。 - Knickedi
如果您不想删除所有应用程序数据(例如,如果有其他正常工作的数据库,您不想删除),我建议通过Android调试监视器进入并仅删除有问题的SQLite数据库文件。当我处于这种情况时,这对我非常有效。 - Godsmith
最好使用theContext.getDatabasePath(DB_NAME).toString()而不是硬编码路径。 - DeveloperX

11

这是一个相当愚蠢的实现限制。 :-) 确保数据库名称具有 .db 扩展名。如果没有扩展名,onCreate() 将不会被调用。


1
哇...非常感谢!这让我疯狂了!...真是愚蠢! - Mahm00d
1
甚至在Android文档中也找不到。他们提供的示例中也没有它。http://developer.android.com/training/search/search.html - Neta
哇塞!非常感谢!这个东西让我疯了!+1,你太棒了。 - Arthur Melo

0

SQLiteOpenHelper.onCreate() 在应用程序的持久存储(即SD卡)中不存在数据库时被调用,而且是在 SQLiteOpenHelper.getWritableDatabase() (或者在 SQLiteOpenHelper.getReadableDatabase() )之后。换句话说,如果代码成功创建了一个存储在持久存储中的数据库,那么 onCreate() 只会被调用一次。如果数据库已经存在于持久存储中,但你正在更改其模式,则使用 SQLiteOpenHelper.onUpgrade(),当你以前没有使用过的版本号打开一个数据库时,它会被调用。在这个方法中,你可以删除旧的模式对象,然后调用 SQLiteOpenHelper.onCreate() 来创建新的模式。如果你想在每次打开数据库时运行代码(由 SQLiteOpenHelper.get[Writable,Readable]Database() 回调的代码),则实现 onOpen()。然后从 SQLiteOpenHelper.onCreate()SQLiteOpenHelper.onOpen() 中的每一个调用一个初始化你的数据库的方法(或针对你的数据库初始化的代码)。

例如,您可能想要使用对SQLiteDatabase的引用,以调用数据管理方法,如SQLiteDatabase.execSQL()
在每个中。
SQLiteOpenHelper.onCreate(SQLiteDatabase db)

SQLiteOpenHelper.onOpen(SQLiteDatabase db)

调用类似于以下的内容

void initDB(SQLiteDatabase db)
{
    this.db = db;
}

在 Android 多任务处理您的进程时,还有其他对象生命周期事件会回调您代码中的处理程序,您应该处理它们。但至少您的数据库处理代码必须处理 SQLiteOpenHelper.onCreate()SQLiteOpenHelper.onOpen()


0

我也遇到了同样的问题。我找到了两个解决方法:

  1. 重启模拟器并勾选“擦除用户数据”。 我的模拟器重启比较慢,所以……
  2. 更改数据库的版本号并重新调用“OnCreate”,这将给我一个当前版本的数据库。我失去了存储的信息(没什么大不了的)。

祝你好运!


0
我曾经遇到过同样的问题。在我的SQL_Create字符串中,我忘记了两个SQL命令之间的空格,因此我需要的列没有被正确实现,但是当我找到并修复了字符串中的错误时,它并没有解决问题,因为应用程序已经将该数据库注册为具有该表。所以onCreate从未被调用。对我来说,最简单的解决方案是更新版本号。这将创建一个新的数据库和表(正确),并修复了应用程序的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接