我尝试创建一个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;
}
}
答案 0 :(得分:29)
在调用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}}内的方法被执行。
<强>解释强>
上述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
答案 3 :(得分:1)
正如官方文档所说,“ getWritableDatabase()创建和/或打开将用于读写的数据库。第一次调用它时,数据库将被打开并且onCreate将调用(SQLiteDatabase),onUpgrade(SQLiteDatabase,int,int)和/或onOpen(SQLiteDatabase)。“
成功打开后,数据库将被缓存,因此您可以在每次需要写入数据库时调用此方法。 (确保在不再需要数据库时调用close()。)错误权限或完整磁盘等错误可能导致此方法失败,但如果问题得到解决,将来的尝试可能会成功。