当调用SQLiteOpenHelper onCreate方法时?

时间:2013-03-24 06:54:29

标签: sqlite android-sqlite

我尝试创建一个SQLite数据库并用它做一些事情。但我发现我的onCreate方法甚至没有被调用!!

我正在onCreate方法的开头向LogCat发送消息。

我的假设是,(超级)构造函数将调用onCreate方法。是吗?

我的代码:

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

public class DatabaseHandler extends SQLiteOpenHelper {
    // Static Constants
    /*** Database details ***/
    // Database version
    private static final int DATABASE_VERSION           = 1;

    // Database name
    private static final String DATABASE_NAME           = "database_name";

    /*** Database Tables ***/
    /** Events **/
    // Event table
    private static final String TABLE_EVENT             = "event";

    // Event table columns
    private static final String COLUMN_EVENT_EID        = "_eid";

    private static final String COLUMN_EVENT_CREATION_DATE  = "creation_date";

    private static final String COLUMN_EVENT_TITLE      = "title";
    private static final String COLUMN_EVENT_ICON       = "icon";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.e("MyApp", "onCreate invoked");
        // Tables creation queries
        String CREATE_EVENT_TABLE = "create table " + TABLE_EVENT + "(" + COLUMN_EVENT_EID + " integer primary key, "
                + COLUMN_EVENT_CREATION_DATE + " text, "
                + COLUMN_EVENT_TITLE + " text, "
                + COLUMN_EVENT_ICON + " text)";

        // Creating tables
        db.execSQL(CREATE_EVENT_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.e("MyApp", "onUpgrade invoked");
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_EVENT);
    }
}

MainActivity Code:

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DatabaseHandler db = new DatabaseHandler(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

4 个答案:

答案 0 :(得分:29)

documentation说:

  

在调用getWritableDatabase()getReadableDatabase()之一之前,实际上并未创建或打​​开数据库。

答案 1 :(得分:2)

你是对的,(超级)构造函数将调用onCreate方法,但仅当实际数据库不退出时才会调用。 来自http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onCreate%28android.database.sqlite.SQLiteDatabase%29

  

用于管理数据库创建和版本管理的帮助程序类。

     

您创建了一个实现onCreate(SQLiteDatabase)的子类,   onUpgrade(SQLiteDatabase,int,int)和可选项   onOpen(SQLiteDatabase),这个类负责打开   数据库(如果存在),如果不存在则创建它,并将其升级为   必要的。

答案 2 :(得分:2)

让我清楚一下逻辑流程。这是延迟初始化概念。

DatabaseHandler 上的(超级)构造函数不会调用onCreate方法。调用 DatabaseHandler 构造函数将初始化:context,数据库名称,创建数据库的工厂,数据库版本和数据库错误处理程序。

getWritableDatabase()> getDatabaseLocked()> - SQLiteDatabase.create()

OR

getReadableDatabase()> getDatabaseLocked()> - SQLiteDatabase.create()

答案:成功创建数据库后,您的配置会再次发生变化getReadableDatabase()getWritableDatabase()来电getDatabaseLocked()onCreate(db) <{1}}内的方法被执行。

enter image description here

<强>解释

上述getDatabaseLocked()方法负责在磁盘中创建SQLiteDatabase。

但延迟初始化的过程(意思是,它并没有使一切准备就绪。如果你需要它,它会在运行时创建那些对象。为此它使用了很多SQLiteDatabase.create()语句)。

如果您看到if..else的完整正文,则会在下方。 [您可以在getDatabaseLocked() 的正文中搜索onCreate()方法

getDatabaseLocked()

请注意,在private SQLiteDatabase getDatabaseLocked(boolean writable) { if (mDatabase != null) { if (!mDatabase.isOpen()) { // Darn! The user closed the database by calling mDatabase.close(). mDatabase = null; } else if (!writable || !mDatabase.isReadOnly()) { // The database is already open for business. return mDatabase; } } if (mIsInitializing) { throw new IllegalStateException("getDatabase called recursively"); } SQLiteDatabase db = mDatabase; try { mIsInitializing = true; if (db != null) { if (writable && db.isReadOnly()) { db.reopenReadWrite(); } } else if (mName == null) { db = SQLiteDatabase.create(null); } else { try { if (DEBUG_STRICT_READONLY && !writable) { final String path = mContext.getDatabasePath(mName).getPath(); db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY, mErrorHandler); } else { db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ? Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0, mFactory, mErrorHandler); } } catch (SQLiteException ex) { if (writable) { throw ex; } Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", ex); final String path = mContext.getDatabasePath(mName).getPath(); db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY, mErrorHandler); } } onConfigure(db); final int version = db.getVersion(); if (version != mNewVersion) { if (db.isReadOnly()) { throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to " + mNewVersion + ": " + mName); } db.beginTransaction(); try { if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } } onOpen(db); if (db.isReadOnly()) { Log.w(TAG, "Opened " + mName + " in read-only mode"); } mDatabase = db; return db; } finally { mIsInitializing = false; if (db != null && db != mDatabase) { db.close(); } } } 方法的正文中,有很多if .. else案例。这些if .. else案例确定了您当前的环境(配置),并根据您当前的环境调用适当的方法来初始化/配置所需的任何内容。

另外,请注意: getDatabaseLocked()(实施DatabaseHandler的类)中的所有回调方法都会在SQLiteOpenHelper正文中调用。

源代码getDatabaseLocked()https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteOpenHelper.java

源代码SQLiteOpenHelper.java:  https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/database/sqlite/SQLiteDatabase.java

要遵循的示例:https://github.com/uddhavgautam/SQLiteBasicSample

答案 3 :(得分:1)

正如官方文档所说,“ getWritableDatabase()创建和/或打开将用于读写的数据库。第一次调用它时,数据库将被打开并且onCreate将调用(SQLiteDatabase),onUpgrade(SQLiteDatabase,int,int)和/或onOpen(SQLiteDatabase)。“

成功打开后,数据库将被缓存,因此您可以在每次需要写入数据库时​​调用此方法。 (确保在不再需要数据库时调用close()。)错误权限或完整磁盘等错误可能导致此方法失败,但如果问题得到解决,将来的尝试可能会成功。

http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#getWritableDatabase()