首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android - Oncreate

Android - Oncreate
EN

Stack Overflow用户
提问于 2022-11-24 17:02:13
回答 1查看 23关注 0票数 0

我试图创建一个DataBase,在这里我需要创建DataBase,而打开应用程序时不会被任何Onclick方法触发。我真的需要帮忙吗?

我试图通过主类onCreate调用它,但它退出了应用程序。

代码语言:javascript
复制
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DataBaseHelper dbh = new DataBaseHelper(MainActivity.this);
    dbh.onCreate();
}
EN

回答 1

Stack Overflow用户

发布于 2022-11-25 21:08:11

简而言之,您不会尝试调用onCreate方法。这样做,就像您已经做过的那样,当数据库实际上还没有创建时,就会调用它,因此可能会得到一个空指针异常。

更具体地说,当您实例化DataBaseHelper时,它实际上并不创建数据库,它只在尝试访问数据库并且调用getWritableDatabasegetReadableDatabase时才这样做,在这种情况下,数据库将被打开。

  • 注意到getReadableDatabase将获得一个可写数据库。不同之处在于,在某些罕见的情况下,getReadableDatabase可能返回只能读取的数据库。根据

代码语言:javascript
复制
-   This will be the same object returned by getWritableDatabase() unless some problem, such as a full disk, requires the database to be opened read-only. In that case, a read-only database object will be returned.
代码语言:javascript
复制
- [https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper#getReadableDatabase()](https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper#getReadableDatabase(%29)

如果在打开数据库的过程中,数据库不存在,那么在创建数据库之后,onCreate方法被称为,而传递给onCreate方法的SQLiteDatabase是一个现有的数据库。然后,onCreate方法允许将表、索引、视图、触发器添加到数据库中。

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

A FIX

不要调用SQLiteOpenHelper方法,而是让onCreate方法在需要时调用onCreate方法。

您可以使用getWritableDatabase()getReadableDatabase()强制这样做,而无需执行任何其他操作。你可以:-

代码语言:javascript
复制
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*/
}

Demonstration

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

代码语言:javascript
复制
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方法,记录结果。在创建单个表之前,
  2. onCreate方法从sqlite_master表(数据库模式)中提取现有组件。

所使用的活动代码与您的类似,但是有更多的方法调用/代码来记录信息。:-

代码语言:javascript
复制
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();
    }
}

结果

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

代码语言:javascript
复制
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: <<<<<

因此,在实例化

  • 之后,数据库不存在(空格之前的第一行).

当调用android_metadata方法时,按照第二个集合,onCreate方法被自动调用,模式被转储,唯一存在的表是

  • (实际上sqlite_master存在,以及它必须存在)。

代码语言:javascript
复制
- android\_metadata is a table unique to android and embedded SQLite API, it stores the locale enabling it's management from the SQLite perspective.

  • doesDBExist的第二个调用现在显示该文件确实存在。

最后,从

  • 提取的sqlite_master显示,现在存在the_table表,并由onCreate方法.

创建。

后续运行

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

代码语言:javascript
复制
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 (因为现在存在数据库),而且存在表。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74564168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档