Java 当第一次打开数据库触发Oncreate时,无法从SQLite Helper Oncreate打开SQLite数据库

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

当mainactivity在安装应用程序后第一次尝试打开数据库时,会触发SQLiteHelper Oncreate方法(正如人们所期望的那样)。然后,我想在OnCreate中创建datatables之后填充数据库,但这样做需要我在content creator类(从OnCreate调用)中再次打开数据库。应用程序尝试在content creator类中打开数据库时崩溃

基本上,我试图在数据库创建后填充它,但显然没有按正确的方式进行

来自SQLiteHelper类的

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的扩展,感谢您接受以下答案: