为什么我的构造函数没有被调用?

时间:2014-04-12 00:00:48

标签: android ddms sqliteopenhelper android-handler class-constructors

我试图将一些记录添加到SQLite表中,但LogCat告诉我该表不存在。 DDMS显示,是的,该表尚未创建/尚未创建。

然而,我确实在SQLiteOpenHelper类中创建了表:

public class SQLiteHandlerDeliveryItem extends SQLiteOpenHelper {
    . . .
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        String CREATE_DELIVERYITEMS_TABLE = "CREATE TABLE " +
                TABLE_DELIVERYITEMS + "("
                + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_INVOICENUM + " TEXT,"
                + COLUMN_UPCPLU + " TEXT," + COLUMN_VENDORITEMID + " TEXT,"
                + COLUMN_PACKSIZE + " INTEGER," + COLUMN_DESCRIPTION + " TEXT,"
                //+ COLUMN_COST + " REAL,"  + COLUMN_MARGIN + " REAL," + COLUMN_LISTPRICE + " REAL,"
                + COLUMN_COST + " REAL DEFAULT 0,"  + COLUMN_MARGIN + " REAL DEFAULT 0," + 

COLUMN_LISTPRICE + " REAL DEFAULT 0,"
                + COLUMN_DEPTNUM + " INTEGER," + COLUMN_SUBDEPT + " TEXT," + COLUMN_QTY + " TEXT"
                + ")";
        sqLiteDatabase.execSQL(CREATE_DELIVERYITEMS_TABLE);
    }

我打电话给班级添加记录的方法:

SQLiteHandlerDeliveryItem sqliteHandler = new SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);
sqliteHandler.addDeliveryItem(delItem);

这应该调用SQLiteHandlerDeliveryItem的构造函数(当sqliteHandler被实例化时),但它不会!我在onCreate()方法中有一个断点,果然 - 它永远不会到达。

为什么呢?我如何强制调用构造函数,以便创建表?

奇怪[est]的事情是我在另一个(工作)SQLiteOpenHelper类中放置了一个断点,而没有达到......什么?!?它至少工作过一次,因为该表确实存在/是从该代码创建的。

所以在我的挥杆中显然有一个洞;我误解或做错了什么?

更新

我很快就将答案标记为答案。

至于:

" 1。您必须在某个时刻调用getWritableDatabase()或getReadableDatabase()。"

执行在每个创建或读取记录的方法中调用getWritableDatabase(),如下所示:

public long addDeliveryItem(DeliveryItem delItem) {
    long IdAdded = 0;
    ContentValues values = new ContentValues();
    values.put(COLUMN_INVOICENUM, delItem.get_invoiceNumber());
    . . .
    values.put(COLUMN_QTY, delItem.get_quantity());

    SQLiteDatabase db = this.getWritableDatabase(); <= Rot Cheer

    if (db != null) {
        IdAdded = db.insert(TABLE_DELIVERYITEMS, null, values);
    }
    . . .

......至于:

&#34; 2。在SQLiteHandlerDeliveryItem的构造函数中,您必须调用super(...)。&#34;

在扩展SQLiteOpenHelper的类中调用调用super:

public SQLiteHandlerDeliveryItem(Context context, SQLiteDatabase.CursorFactory factory)     
{
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

所以......我仍然不知道问题/解决方案是什么......

更新2

所以我在尝试在LogCat中将记录插入此表时看到的是:

E / SQLiteLog:(1)没有这样的表:deliveryitems

然而,我尝试添加记录的代码实例化了扩展SQLiteOpenHelper的相应/适当的类,如下所示:

else if ("Delivery Items".equals(tableName)) {
    try {
        JSONArray jsonArr = new JSONArray(result);
        for (int i = 0; i < jsonArr.length(); i++) {
            JSONObject jsonObj = jsonArr.getJSONObject(i);
            String invNum = jsonObj.getString("invoiceNumber");
        . . .                        
        // Prepare for writing to db
        DeliveryItem delItem = new DeliveryItem();
        delItem.set_invoiceNumber(invNum);
        . . .                        
        SQLiteHandlerDeliveryItem sqliteHandler = new  
            SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);
        sqliteHandler.addDeliveryItem(delItem);
    }
}

...并且该类具有创建表的代码:

public class SQLiteHandlerDeliveryItem extends SQLiteOpenHelper {
        . . .
public SQLiteHandlerDeliveryItem(Context context, SQLiteDatabase.CursorFactory factory)   
{
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
    String CREATE_DELIVERYITEMS_TABLE = "CREATE TABLE " +
            TABLE_DELIVERYITEMS + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_INVOICENUM + " TEXT,"
            + COLUMN_UPCPLU + " TEXT," + COLUMN_VENDORITEMID + " TEXT,"
            + COLUMN_PACKSIZE + " INTEGER," + COLUMN_DESCRIPTION + " TEXT,"
            + COLUMN_COST + " INTEGER,"  + COLUMN_MARGIN + " INTEGER," + COLUMN_LISTPRICE + " INTEGER,"
            + COLUMN_DEPTNUM + " INTEGER," + COLUMN_SUBDEPT + " TEXT," + COLUMN_QTY + " TEXT"
            + ")";
    sqLiteDatabase.execSQL(CREATE_DELIVERYITEMS_TABLE);
}

那么......我做错了什么,或者做错了什么?

更新3

确实没有创建表格。 LogCat中的错误消息表明情况就是这样(它没有这样的表:交付项目&#34;)。

我的构造函数如下所示:

@Override
public void onCreate(SQLiteDatabase db) {
    String CREATE_DELIVERYITEMS_TABLE = "CREATE TABLE " +
            TABLE_DELIVERYITEMS + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_INVOICENUM + " TEXT,"
            + COLUMN_UPCPLU + " TEXT," + COLUMN_VENDORITEMID + " TEXT,"
            + COLUMN_PACKSIZE + " INTEGER," + COLUMN_DESCRIPTION + " TEXT,"
            + COLUMN_COST + " INTEGER,"  + COLUMN_MARGIN + " INTEGER," + COLUMN_LISTPRICE + " INTEGER,"
            + COLUMN_DEPTNUM + " INTEGER," + COLUMN_SUBDEPT + " TEXT," + COLUMN_QTY + " TEXT"
            + ")";
    db.execSQL(CREATE_DELIVERYITEMS_TABLE);
}

这段代码确实输入了 。那么我必须跳过什么箍才能调用构造函数?

我认为当我实例化类时会发生这种情况:

SQLiteHandlerDeliveryItem sqliteHandler = new 
    SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);

即使调用它,构造函数如何知道arg(SQLiteDatabase db)是什么 - 它从何处获取此值?

我有一个数据库,有一个表。它只是拒绝添加第二个表。

正如某人推荐的那样,我正在添加一个单独的类,为每个要添加到数据库的表扩展SQLiteOpenHelper。

当我到达那条线时:

SQLiteHandlerDeliveryItem sqliteHandler = new 
    SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);

...并且将F7混入其中,我到达了类构造函数:

public SQLiteHandlerDeliveryItem(Context context, SQLiteDatabase.CursorFactory factory)  
{
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

...但不是onCreate事件。

所以它&#34;难怪&#34;我没有deliveryitems表,因为创建表的代码永远不会到达;但是为什么它没有达到 - 我必须做些什么才能达到它?

3 个答案:

答案 0 :(得分:1)

  1. 您必须在某个时候致电getWritableDatabase()getReadableDatabase()

  2. SQLiteHandlerDeliveryItem的构造函数中,您必须调用super(...)。

答案 1 :(得分:1)

首先,方法SQLiteOpenHelper.onCreate()不是构造函数。我不确定,但看起来你在问题中混合了两个概念。


现在试图解决问题......

好像你的桌子没有被创建。来自SQLiteOpenHelper.onCreate()的{​​{3}}:

public abstract void onCreate (SQLiteDatabase db)

Called when the database is created for the first time. This is where the creation of tables and the initial population of the tables should happen.

因此,对于典型用例,此方法只会被调用一次 - 首次安装应用程序时(首先使用数据库)。此时,调用onCreate()来创建实际表。但是每次运行应用程序时都不会调用此方法。

我的建议是检查这是否是问题 - 卸载应用,然后重试。在此方法中放置一个断点,以确保它确实可以运行。

有时可能发生的是我们在应用程序上有一个数据库,然后更新内容以添加表,并忘记卸载。另一种正确的方法是使用onUpgrade()方法添加新表。

让我知道这是怎么回事,或者我是否误解了这个问题。

答案 2 :(得分:0)

正如我所希望的,它实际上是一个简单的修复:只需增加数据库版本的值。我在p上读到了这个。 O'Reilly的“Programming Android”中的262个:

DATABASE_VERSION ...如果计算机上的数据库版本小于DATABASE_VERSION,系统将运行onUpgrade方法将数据库升级到当前级别。

因此,您需要做的就是增加该数字:

    private static final int DATABASE_VERSION = 2; 
    // I changed it from "1" to "2", but you could change it to anything you want, I reckon (42, or 1776, or whatever).

增加版本值会导致onUpgrade运行,这会丢弃旧版本的数据库,然后调用onCreate:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_DELIVERYITEMS);
    onCreate(db);
}

然后onCreate()事件就是这样 - 添加DDL来创建表。

以下是类中的相关代码,它在上下文中扩展了SQLiteOpenHelper:

public class SQLiteHandlerDeliveryItem extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 2; 
private static final String DATABASE_NAME = "HHS.db";
private static final String TABLE_DELIVERYITEMS = "deliveryitems";

private static final String COLUMN_ID = "_id";
. . .
private static final String COLUMN_QTY = "quantity";

public SQLiteHandlerDeliveryItem(Context context, SQLiteDatabase.CursorFactory factory)  
{
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
    String CREATE_DELIVERYITEMS_TABLE = "CREATE TABLE " +
            TABLE_DELIVERYITEMS + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_INVOICENUM + " TEXT,"
. . .
            + COLUMN_DEPTNUM + " INTEGER," + COLUMN_SUBDEPT + " TEXT," + COLUMN_QTY + " 
TEXT"
            + ")";
    db.execSQL(CREATE_DELIVERYITEMS_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_DELIVERYITEMS);
    onCreate(db);
}
. . .

所以在我看来,有多个扩展SQLiteOpenHelper的类是一件好事,因为你可以保持你的代码分离,而不是有一对巨大的/大量的onUpgrade / onCreate spaghetti。