Java 当第一次打开数据库触发Oncreate时,无法从SQLite Helper Oncreate打开SQLite数据库
当mainactivity在安装应用程序后第一次尝试打开数据库时,会触发SQLiteHelper Oncreate方法(正如人们所期望的那样)。然后,我想在OnCreate中创建datatables之后填充数据库,但这样做需要我在content creator类(从OnCreate调用)中再次打开数据库。应用程序尝试在content creator类中打开数据库时崩溃 基本上,我试图在数据库创建后填充它,但显然没有按正确的方式进行 来自SQLiteHelper类的:Java 当第一次打开数据库触发Oncreate时,无法从SQLite Helper Oncreate打开SQLite数据库,java,android,android-sqlite,Java,Android,Android Sqlite,当mainactivity在安装应用程序后第一次尝试打开数据库时,会触发SQLiteHelper Oncreate方法(正如人们所期望的那样)。然后,我想在OnCreate中创建datatables之后填充数据库,但这样做需要我在content creator类(从OnCreate调用)中再次打开数据库。应用程序尝试在content creator类中打开数据库时崩溃 基本上,我试图在数据库创建后填充它,但显然没有按正确的方式进行 来自SQLiteHelper类的: public class d
public class dbContents {
public static void baseContents(Context context) {
dbDataSource ds = new dbDataSource(context);
ds.open();
public dbDataSource(Context context) {
dbHelper = new MySQLiteHelper(context);
DatabaseVersion = dbHelper.DatabaseVersion; //used when MainActivity onResume to know if it needs to repopulate reminders
}
public void open() throws SQLException {
database = dbHelper.getWritableDatabase(); //crashes here
}
来自内容创建者类:
public class dbContents {
public static void baseContents(Context context) {
dbDataSource ds = new dbDataSource(context);
ds.open();
public dbDataSource(Context context) {
dbHelper = new MySQLiteHelper(context);
DatabaseVersion = dbHelper.DatabaseVersion; //used when MainActivity onResume to know if it needs to repopulate reminders
}
public void open() throws SQLException {
database = dbHelper.getWritableDatabase(); //crashes here
}
来自dbDataSource类:
public class dbContents {
public static void baseContents(Context context) {
dbDataSource ds = new dbDataSource(context);
ds.open();
public dbDataSource(Context context) {
dbHelper = new MySQLiteHelper(context);
DatabaseVersion = dbHelper.DatabaseVersion; //used when MainActivity onResume to know if it needs to repopulate reminders
}
public void open() throws SQLException {
database = dbHelper.getWritableDatabase(); //crashes here
}
它似乎在database=dbHelper.getWritableDatabase()行崩溃;在open()方法中。重申一下,在主活动中打开数据库时,将调用SQLITEHeloper OnCreate。当数据库在mainactivity中打开时,它正在调用上面发布的同一个open()方法,当从dbcontents类调用该方法时,它将崩溃。这是线程问题吗?您不应该尝试从
SQLiteOpenHelper
调用getWritableDatabase()
或getReadableDatabase()
生命周期方法,例如onCreate()
或从那里调用的方法。这将失败,出现“递归调用”异常
相反,使用作为
onCreate()
或其他生命周期方法的参数提供的SQLiteDatabase
。您不应该尝试从SQLiteOpenHelper
生命周期方法(如onCreate())调用getWritableDatabase()
或getReadableDatabase()
或从那里调用的方法。这将失败,出现“递归调用”异常
相反,请使用SQLiteDatabase
,它作为onCreate()
或其他生命周期方法的参数提供。我已经编写了一些代码片段,可以帮助您填充SQLite数据库
,您可以查看工作示例
创建一个类名CreateDatabase.java
,它的全部目的是创建数据库并向其中添加一个表
public class CreateDatabase extends SQLiteOpenHelper implements BaseColumns {
private static final String DATABASE_NAME = "database_name.sqlite";
private static final int DATABASE_VERSION = 1;
public static final String TEXT_TYPE = " TEXT";
public static final String COMMA_SEP = ",";
public CreateDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("CreateDatabase: ","onCreate: called for the first time");
db.execSQL(SQL_CREATE_TEST_ONE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public static final String SQL_CREATE_TEST_ONE_TABLE = "CREATE TABLE IF NOT EXISTS " + "TestOne_Table" +
" (" + BaseColumns._ID + " INTEGER PRIMARY KEY," +
"first_column_name" + TEXT_TYPE + COMMA_SEP +
"second_column_name" + TEXT_TYPE + ")";
}
既然您有了这个类,您需要找到一种方法,在应用程序启动后立即使用它创建数据库,正如您所知,onCreate()
只会被调用一次,因此下面的代码只在第一次创建数据库时才起作用,请将它放在应用程序打开时可以调用的地方
CreateDatabase createAllTables = new CreateDatabase(getApplicationContext());
SQLiteDatabase database = createAllTables.getWritableDatabase();
这些行将帮助您创建数据库
运行完这些行后,您可以在DDMS
中看到数据库,如下所示,您可以在SQLite浏览器
或Mozilla Sqlit管理器
在成功创建数据库之后,您可以使用以下代码用一些数据填充它,我已经将一些值作为示例显示
public class SqliteTestOneActivity extends AppCompatActivity {
private Button save_Button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_test_one);
initializeUI();
}
private void initializeUI() {
save_Button = (Button) findViewById(R.id.SqliteTestOneActivity_button);
save_Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyReader myReader = new MyReader(getApplicationContext());
myReader.open();
myReader.insert("Jack", "Sam");
myReader.close();
}
});
}
private static class MyReader {
private static final String Table_Name = "TestOne_Table";
private final Context mCtx;
private SQLiteDatabase mDb;
private InternalHelper mDbHelper;
public MyReader(Context mCtx) {
this.mCtx = mCtx;
}
public MyReader open() {
this.mDbHelper = new InternalHelper(this.mCtx);
this.mDb = mDbHelper.getWritableDatabase();
return this;
}
public void insert(String first, String second) {
ContentValues values = new ContentValues();
values.put("first_column_name", first);
values.put("second_column_name", second);
mDb.insert(Table_Name, null, values);
}
public void close() {
if (mDbHelper != null) {
mDbHelper.close();
}
}
private static class InternalHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "database_name.sqlite";
private static final int DATABASE_VERSION = 1;
public InternalHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase paramSQLiteDatabase) {
}
public void onUpgrade(SQLiteDatabase paramSQLiteDatabase, int paramInt1, int paramInt2) {
}
}
}
}
运行此活动后,单击“保存”按钮,您的数据将保存在数据库中,您可以从DDMS中提取数据库并检查记录
输出
我已经编写了一些代码片段,可以帮助您填充SQLite数据库
,您可以在上面查看工作示例
创建一个类名CreateDatabase.java
,它的全部目的是创建数据库并向其中添加一个表
public class CreateDatabase extends SQLiteOpenHelper implements BaseColumns {
private static final String DATABASE_NAME = "database_name.sqlite";
private static final int DATABASE_VERSION = 1;
public static final String TEXT_TYPE = " TEXT";
public static final String COMMA_SEP = ",";
public CreateDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d("CreateDatabase: ","onCreate: called for the first time");
db.execSQL(SQL_CREATE_TEST_ONE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public static final String SQL_CREATE_TEST_ONE_TABLE = "CREATE TABLE IF NOT EXISTS " + "TestOne_Table" +
" (" + BaseColumns._ID + " INTEGER PRIMARY KEY," +
"first_column_name" + TEXT_TYPE + COMMA_SEP +
"second_column_name" + TEXT_TYPE + ")";
}
既然您有了这个类,您需要找到一种方法,在应用程序启动后立即使用它创建数据库,正如您所知,onCreate()
只会被调用一次,因此下面的代码只在第一次创建数据库时才起作用,请将它放在应用程序打开时可以调用的地方
CreateDatabase createAllTables = new CreateDatabase(getApplicationContext());
SQLiteDatabase database = createAllTables.getWritableDatabase();
这些行将帮助您创建数据库
运行完这些行后,您可以在DDMS
中看到数据库,如下所示,您可以在SQLite浏览器
或Mozilla Sqlit管理器
在成功创建数据库之后,您可以使用以下代码用一些数据填充它,我已经将一些值作为示例显示
public class SqliteTestOneActivity extends AppCompatActivity {
private Button save_Button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_test_one);
initializeUI();
}
private void initializeUI() {
save_Button = (Button) findViewById(R.id.SqliteTestOneActivity_button);
save_Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyReader myReader = new MyReader(getApplicationContext());
myReader.open();
myReader.insert("Jack", "Sam");
myReader.close();
}
});
}
private static class MyReader {
private static final String Table_Name = "TestOne_Table";
private final Context mCtx;
private SQLiteDatabase mDb;
private InternalHelper mDbHelper;
public MyReader(Context mCtx) {
this.mCtx = mCtx;
}
public MyReader open() {
this.mDbHelper = new InternalHelper(this.mCtx);
this.mDb = mDbHelper.getWritableDatabase();
return this;
}
public void insert(String first, String second) {
ContentValues values = new ContentValues();
values.put("first_column_name", first);
values.put("second_column_name", second);
mDb.insert(Table_Name, null, values);
}
public void close() {
if (mDbHelper != null) {
mDbHelper.close();
}
}
private static class InternalHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "database_name.sqlite";
private static final int DATABASE_VERSION = 1;
public InternalHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase paramSQLiteDatabase) {
}
public void onUpgrade(SQLiteDatabase paramSQLiteDatabase, int paramInt1, int paramInt2) {
}
}
}
}
运行此活动后,单击“保存”按钮,您的数据将保存在数据库中,您可以从DDMS中提取数据库并检查记录
输出
你知道哪个参数是空的吗?我编辑了这篇文章并缩小了崩溃的位置…我认为你应该粘贴错误代码,如果你能调试找到哪个参数是空的,最好告诉我们。你应该在每次操作(查询、命令等)或批处理(事务)时始终打开和关闭数据库。你能知道哪个参数是空的吗?我编辑了文章,缩小了崩溃的位置…我认为你应该粘贴错误代码,如果你能调试找到哪个参数是空的,你最好告诉我们。你应该在每次操作(查询、命令等)或批处理(事务)时始终打开和关闭数据库。谢谢。看来你的答案和laalto的答案都为我澄清了问题。我会给你支票,因为我在回答中付出了很大的努力。基本上,对于未来的读者来说,我不能做我试图做的事情。从调用onCreate-->的活动-->打开数据库,然后再次打开数据库进行填充。您将展示一个在活动中完成填充的示例。这实际上是我在试图“简化”它之前开始的地方。你的例子给了我一些好主意。一个问题:您使用什么来查看数据库。您是否在您的计算机或设备上查看?@EdwardBagby,您可以使用SQLite浏览器查看您的数据库,您的另一个选项是您在Mozilla call SQLite Manager上获得的插件,它是一个可添加到firefox的扩展,感谢您接受以下答案: