Android Studio SQLiteOpenHelper -创建时

t1qtbnec  于 2022-11-27  发布在  Android
关注(0)|答案(1)|浏览(121)

我试图创建一个数据库,我需要我的数据库被创建,而我打开我的应用程序不被任何Onclick方法触发。我真的可以使用一些帮助?
我试图通过主类onCreate调用它,但它退出了应用程序。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DataBaseHelper dbh = new DataBaseHelper(MainActivity.this);
    dbh.onCreate();
}
vuktfyat

vuktfyat1#

简而言之,不要试图调用onCreate方法,这样做会在数据库还没有创建的时候调用它,因此可能会得到一个空指针异常。
更具体地说,当您示例化DataBaseHelper时,它实际上并不创建数据库,它只在您尝试访问数据库时创建数据库,并且在打开数据库的情况下调用getWritableDatabasegetReadableDatabase

  • 请注意,getReadableDatabase将获得一个可写的数据库。细微的区别在于,getReadableDatabase可能在某些罕见的情况下返回一个只能读取的数据库。
  • 这将是getWritableDatabase()返回的同一对象,除非出现某些问题(如磁盘已满),需要以只读方式打开数据库。在这种情况下,将返回一个只读数据库对象。
  • 数据库中的数据类型

如果在打开数据库的过程中,数据库不存在,则在创建数据库**之后调用onCreate方法,**并且传递给onCreate方法的SQLiteDatabase是一个现有数据库。然后,onCreate方法允许您向数据库添加表、索引、视图、触发器。

  • 创建数据库时(在调用onCreate之前,它将具有2个表sqlite_master(模式)和android_metadata(存储设备的区域设置),这些是系统表)。
    修复

不要调用onCreate方法,而是让SQLiteOpenHelper在需要时调用onCreate方法。
您可以使用getWritableDatabase()getReadableDatabase()强制执行此操作,而无需执行任何其他操作。例如,您可以有:-

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DataBaseHelper dbh = new DataBaseHelper(MainActivity.this); /* NOTE only instantiates the helper, it does not create the database */
    //dbh.onCreate(); /*<<<<<<<<<< COMMENTED OUT */
    SQLiteDatabase db = dbh.getWritableDatabase(); /*<<<<<<<<<< ADDED to force an open and if need be the one-time creation of the database*/
}

示范

下面是一个演示上述内容的示例。DataBaseHelper为:-

class DataBaseHelper extends SQLiteOpenHelper {

    public static final String DATABASE_FILENAME = "the_database.db";
    public static final int DATABASE_VERSION_NUMBER = 1;

    DataBaseHelper(Context context) {
        super(context,DATABASE_FILENAME,null,DATABASE_VERSION_NUMBER);
    }

    /*
        NOTE onCreate is only called when an attempt is made to get a writable/readable SQLiteDatabase
        in which case the database is create by the SQLiteOpenHelper.
        If the database already exists then it will not be called. As such onCreate is called only
        once for the lifetime of the database.

     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        /* Demonstrate the database components BEFORE creating any user defined components */
        /* YOU WOULD NOT TYPICALLY DO THIS */
        Cursor csr = db.query("sqlite_master",null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
        csr.close();
        /* Create the user components */
        db.execSQL("CREATE TABLE IF NOT EXISTS the_table (id INTEGER PRIMARY KEY, col1 TEXT)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }

    public boolean doesDBExist(Context context, String tagExtra) {
        String TAG = "DBDEBUG" + tagExtra;
        String path = context.getDatabasePath(this.getDatabaseName()).getPath();
        boolean rv = false;
        if (context.getDatabasePath(this.getDatabaseName()).exists()) {
            rv = true;
            Log.d(TAG,"The database " + this.getDatabaseName() + " exists. It is located at " + path);
        } else {
            StringBuilder sb = new StringBuilder( "\n\tThe databases folder " + context.getDatabasePath(this.getDatabaseName()).getParentFile().getPath());
            rv = false;
            if (context.getDatabasePath(this.getDatabaseName()).getParentFile().exists()) {
                sb.append(" exists.");
            } else {
                sb.append(" does not exist.");
            }
            Log.d(TAG,"The database " + this.getDatabaseName() + " does not exist as location " + path + sb.toString());
        }
        return rv;
    }
}

即一个非常基本的类,它扩展了SQLiteOpenhelper,而不是

  1. doesDBExist方法,检查作为数据库的基础文件是否存在,并记录结果。
    1.在创建单个表之前,onCreate方法从sqlite_master表(数据库模式)中提取现有组件。
    所使用的活动代码与您的类似,但有额外的方法调用/代码来记录信息:-
public class MainActivity extends AppCompatActivity {

    DataBaseHelper dbh;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbh = new DataBaseHelper(this);
        dbh.doesDBExist(this,"STG01"); /* before opening the database see if it exists */
        SQLiteDatabase db = dbh.getWritableDatabase(); /* should open and create db if required */
        dbh.doesDBExist(this,"STG02"); /* should now exist */
        Cursor csr = db.query("sqlite_master",null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
        csr.close();
    }
}

结果

作为新安装运行时,日志包含:-

2022-11-26 09:01:25.121 D/DBDEBUGSTG01: The database the_database.db does not exist as location /data/user/0/a.a.so74564168sqliteoncreatedemo/databases/the_database.db
        The databases folder /data/user/0/a.a.so74564168sqliteoncreatedemo/databases exists.
        
        
2022-11-26 09:01:25.151 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@cf2ef01
2022-11-26 09:01:25.151 I/System.out: 0 {
2022-11-26 09:01:25.151 I/System.out:    type=table
2022-11-26 09:01:25.152 I/System.out:    name=android_metadata
2022-11-26 09:01:25.152 I/System.out:    tbl_name=android_metadata
2022-11-26 09:01:25.152 I/System.out:    rootpage=3
2022-11-26 09:01:25.152 I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
2022-11-26 09:01:25.153 I/System.out: }
2022-11-26 09:01:25.153 I/System.out: <<<<<

2022-11-26 09:01:25.162 D/DBDEBUGSTG02: The database the_database.db exists. It is located at /data/user/0/a.a.so74564168sqliteoncreatedemo/databases/the_database.db

2022-11-26 09:01:25.163 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@40841a6
2022-11-26 09:01:25.163 I/System.out: 0 {
2022-11-26 09:01:25.164 I/System.out:    type=table
2022-11-26 09:01:25.164 I/System.out:    name=android_metadata
2022-11-26 09:01:25.164 I/System.out:    tbl_name=android_metadata
2022-11-26 09:01:25.164 I/System.out:    rootpage=3
2022-11-26 09:01:25.164 I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
2022-11-26 09:01:25.164 I/System.out: }
2022-11-26 09:01:25.164 I/System.out: 1 {
2022-11-26 09:01:25.165 I/System.out:    type=table
2022-11-26 09:01:25.165 I/System.out:    name=the_table
2022-11-26 09:01:25.165 I/System.out:    tbl_name=the_table
2022-11-26 09:01:25.165 I/System.out:    rootpage=4
2022-11-26 09:01:25.165 I/System.out:    sql=CREATE TABLE the_table (id INTEGER PRIMARY KEY, col1 TEXT)
2022-11-26 09:01:25.165 I/System.out: }
2022-11-26 09:01:25.166 I/System.out: <<<<<
  • 因此,示例化DataBaseHelperm后,数据库不存在(空格前的第一行)。
  • 当调用getWritableDatabase方法时,根据第二个集合,将自动调用onCreate方法,并转储模式,唯一存在的表是android_metadata(实际上sqlite_master存在,并且它必须存在)。
  • android_metadata是android和嵌入式SQLite API特有的表,它存储了区域设置,从而能够从SQLiteAngular 进行管理。
  • 现在,对doesDBExist的第二次调用显示该文件确实存在。
  • 最后,从sqlite_master中提取的数据显示,现在the_table表存在,并且是通过onCreate方法创建的。
    后续运行

如果应用程序再次运行,则日志包含:-

2022-11-26 09:22:58.583  D/DBDEBUGSTG01: The database the_database.db exists. It is located at /data/user/0/a.a.so74564168sqliteoncreatedemo/databases/the_database.db

2022-11-26 09:22:58.587  D/DBDEBUGSTG02: The database the_database.db exists. It is located at /data/user/0/a.a.so74564168sqliteoncreatedemo/databases/the_database.db

2022-11-26 09:22:58.587  I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@9c8df94
2022-11-26 09:22:58.587  I/System.out: 0 {
2022-11-26 09:22:58.588  I/System.out:    type=table
2022-11-26 09:22:58.588  I/System.out:    name=android_metadata
2022-11-26 09:22:58.588  I/System.out:    tbl_name=android_metadata
2022-11-26 09:22:58.588  I/System.out:    rootpage=3
2022-11-26 09:22:58.588  I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
2022-11-26 09:22:58.588  I/System.out: }
2022-11-26 09:22:58.588  I/System.out: 1 {
2022-11-26 09:22:58.588  I/System.out:    type=table
2022-11-26 09:22:58.588  I/System.out:    name=the_table
2022-11-26 09:22:58.588  I/System.out:    tbl_name=the_table
2022-11-26 09:22:58.588  I/System.out:    rootpage=4
2022-11-26 09:22:58.588  I/System.out:    sql=CREATE TABLE the_table (id INTEGER PRIMARY KEY, col1 TEXT)
2022-11-26 09:22:58.588  I/System.out: }
2022-11-26 09:22:58.588  I/System.out: <<<<<

即,数据库存在并且已被保留/持久化。未调用onCreate(因为数据库现在存在)并且表存在。

相关问题