Android 是否通过内容提供程序或直接访问DBHelper创建表?其他的?

Android 是否通过内容提供程序或直接访问DBHelper创建表?其他的?,android,sqlite,android-contentprovider,Android,Sqlite,Android Contentprovider,我正在构建一个Android应用程序,它使用一个DB助手类和内容提供者,仅用于访问DB。我注意到,当我的应用程序启动时,它从来没有碰到我的DBHelper类的onCreate(),该类包含表创建的所有DDL(如果它们不存在的话) 我已经手动创建了其中一个表,并且已经确认我可以通过我的提供商执行CRUD操作。我的目标是让内容提供者只访问DBhelper类,并让UI使用内容提供者进行CRUD操作 我觉得我缺少了这张椅子的一部分,需要一些帮助来理解这个过程应该如何工作,这样当我的应用程序启动时,系统将

我正在构建一个Android应用程序,它使用一个DB助手类和内容提供者,仅用于访问DB。我注意到,当我的应用程序启动时,它从来没有碰到我的DBHelper类的onCreate(),该类包含表创建的所有DDL(如果它们不存在的话)


我已经手动创建了其中一个表,并且已经确认我可以通过我的提供商执行CRUD操作。我的目标是让内容提供者只访问DBhelper类,并让UI使用内容提供者进行CRUD操作

我觉得我缺少了这张椅子的一部分,需要一些帮助来理解这个过程应该如何工作,这样当我的应用程序启动时,系统将检查表是否存在,并在不存在时创建

我已经将DBhelper类作为一个单例实现,对此似乎有很多争论

我明白,在创建操作继续之前,我确实需要获得一个可读或可写的db,至少我认为这是正确的。我遇到的问题是,如果我应该在应用程序启动时从我的MainActivity的onCreate中获取我的db类的实例,那么我无法将其拼凑起来?或者,如果我应该在我的内容提供商中做一些事情,在应用程序启动时处理这个问题?仅供参考-我确实在清单中注册了我的内容提供程序,如前所述,在我的MainActivity onCreate()中,我已成功地将我的内容提供程序用于手动生成的表上的CRUD操作

如果您有任何指示,我们将不胜感激

这是我的AppDB类

class AppDatabase extends SQLiteOpenHelper{

    public static final String DATABASE_NAME = "wgutrack.db";
    public static final int DATABASE_VERSION = 1;

    public static final String CTINE          = "CREATE TABLE IF NOT EXISTS ";
    public static final String PKA            = " INTEGER PRIMARY KEY AUTOINCREMENT, ";
    private static final String TEXT_TYPE     = " TEXT";
    public static final String INTEGER_TYPE   = " INTEGER";
    private static final String COMMA_SEP     = ", ";
    private static final String NN            = " NOT NULL ";

    // Implement AppDatabase as a singleton
    private static AppDatabase instance = null;

    private AppDatabase(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /**
     * Get an instance of the app's singleton db helper object
     * @param context The content provider's context
     * @return A SQLite DB helper object
     */
    static AppDatabase getInstance(Context context) {

        if (instance == null) {
            instance = new AppDatabase(context);
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        // Create script for Terms table
        String sqlTerms;
        sqlTerms = CTINE + TermsContract.TABLE_NAME + " ("
                + TermsContract.Columns._ID + PKA
                + TermsContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + TermsContract.Columns.COL_START + INTEGER_TYPE + NN + COMMA_SEP
                + TermsContract.Columns.COL_END + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlTerms);
        db.execSQL(sqlTerms);

        // Create script for Courses table
        String sqlCourses;
        sqlCourses = CTINE + CoursesContract.TABLE_NAME + " ("
                + CoursesContract.Columns._ID + PKA
                + CoursesContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + CoursesContract.Columns.COL_STATUS + TEXT_TYPE + NN + COMMA_SEP
                + CoursesContract.Columns.COL_MENTOR_ID + INTEGER_TYPE + NN + COMMA_SEP
                + CoursesContract.Columns.COL_START + INTEGER_TYPE + COMMA_SEP
                + CoursesContract.Columns.COL_END + INTEGER_TYPE + COMMA_SEP
                + CoursesContract.Columns.COL_START_NOTIFY + INTEGER_TYPE + COMMA_SEP
                + CoursesContract.Columns.COL_END_NOTIFY + INTEGER_TYPE + ")";
        Log.d("SQLQRY", sqlCourses);
        db.execSQL(sqlCourses);

        // Create script for term / course map table
        String sqlMap;
        sqlMap = CTINE + TermsCourseMapContract.TABLE_NAME + " ("
                + TermsCourseMapContract.Columns._ID + PKA
                + TermsCourseMapContract.Columns.COL_TERM_ID + INTEGER_TYPE + COMMA_SEP
                + TermsCourseMapContract.Columns.COL_COURSE_ID + INTEGER_TYPE + ")";

        // Create script for Mentors table
        String sqlMentors;
        sqlMentors = CTINE + MentorsContract.TABLE_NAME + " ("
                + MentorsContract.Columns._ID + PKA
                + MentorsContract.Columns.COL_FIRST_NAME + TEXT_TYPE + NN + COMMA_SEP
                + MentorsContract.Columns.COL_LAST_NAME + TEXT_TYPE + NN + COMMA_SEP
                + MentorsContract.Columns.COL_PHONE + TEXT_TYPE + COMMA_SEP
                + MentorsContract.Columns.COL_EMAIL + TEXT_TYPE + ")";
        Log.d("SQLQRY", sqlMentors);
        db.execSQL(sqlMentors);

        // Create script for Assessments table
        String sqlAssessments;
        sqlAssessments = CTINE + AssessmentsContract.TABLE_NAME + " ("
                + AssessmentsContract.Columns._ID + PKA
                + AssessmentsContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + AssessmentsContract.Columns.COL_DESC + TEXT_TYPE + COMMA_SEP
                + AssessmentsContract.Columns.COL_TYPE + TEXT_TYPE + COMMA_SEP
                + AssessmentsContract.Columns.COL_COURSE_ID + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlAssessments);
        db.execSQL(sqlAssessments);

        // Create script for the Notes table
        String sqlNotes;
        sqlNotes = CTINE + NotesContract.TABLE_NAME + " ("
                + NotesContract.Columns._ID + PKA
                + NotesContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + NotesContract.Columns.COL_TEXT + TEXT_TYPE + NN + COMMA_SEP
                + NotesContract.Columns.COL_COURSE_ID + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlNotes);
        db.execSQL(sqlNotes);

        // Create script for the Goals table
        String sqlGoals;
        sqlGoals = CTINE + GoalsContract.TABLE_NAME + " ("
                + GoalsContract.Columns._ID + PKA
                + GoalsContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + GoalsContract.Columns.COL_DESC + TEXT_TYPE + NN + COMMA_SEP
                + GoalsContract.Columns.COL_DUE_DATE + INTEGER_TYPE + NN + COMMA_SEP
                + GoalsContract.Columns.COL_ASS_ID + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlGoals);
        db.execSQL(sqlGoals);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        switch (oldVersion) {
            case 1:
                // upgrade from version 1
                break;
            default:
                throw new IllegalStateException("onUpgrade() with unknown new version: " + newVersion);
        }
    }
}
我注意到,当我的应用程序启动时,它从来没有击中目标 DBHelper类的onCreate(),该类具有表的所有DDL 创造物,如果它们不存在的话

创建数据库时,
SQLIteOpenHelper
类的
onCreate
方法运行一次。它并不是每次实例化子类的实例时都运行

开发应用程序时,更改数据库结构的最简单方法是执行以下操作之一(假设数据可能丢失):-

  • 从设备上的设置中删除/清除应用程序的数据,然后重新运行应用程序
  • 卸载然后重新安装应用程序,然后重新运行应用程序
  • 在删除表的
    onUpgrade
    方法中使用合适的代码,然后调用已更改的
    onCreate
    方法
如果需要保留数据,则可以使用
onUpgrade
方法在的限制范围内更改表

您可以通过查询sqlite\u master表来检查表是否存在。这将返回一个包含5列的游标,即:-

  • 类型
    • 表格表格
  • 名称实体的名称
  • tbl_name实体相关的表的名称
  • rootpage
  • sql用于创建实体的sql

  • (实体与类型相关,例如表、索引、视图、触发器)

。。。。当我的应用程序启动时,系统将检查表是否存在,以及 当它们不存在时创建

所以要查看tablex,您可以使用

SELECT tbl_name FROM sqlite_master WHERE tbl_name = 'tablex' AND type = 'table';
所以你可以有一个方法,大致如下:-

public boolean doesTableExist(String table_name) {
    boolean rv = false;
    String[] columns = new String[]{"sqlite_master"};
    String whereclause = "tbl_name=? AND type=?";
    String[] whereargs = new String[]{table_name,"table"};
    Cursor csr = yoursqlitedatabase.query("sqlite_master",columns,whereclause,wwhereargs,null,null,null);
    rv = csr.getCount() > 0;
    csr.close();
    return rv;
}
  • 如果在DBhelper中包含上述内容,则
    Cursor csr=yoursqlitedatabase.query(“sqlite_master”,columns,whereclause,wwhereargs,null,null)
    可以是
    Cursor csr=this.getWritableDatabase().query(“sqlite\u master”,columns,where子句,wwhereargs,null,null)

    • 通常您会看到
      SQliteDatabase db=this.getWritabledatabase()
      ,然后看到
      db.query……。

    • 然后,您可以使用类似于
      AppDatabase myDBHlper
      作为类变量,然后在要检查的类(活动)中
      myDBHelper=Appdatabase.getInstance(this)
      后跟
      if(myDBHelper.doestableExist(“您的表”){……}

当然,只要使用
创建表(如果不存在)…
就足够了


您可以通过重写类的
onOpen
方法来实现检查等,该类是SQLiteOpenHelper(又称DBHelper)的子类,或者是
onConfigure
方法。

“我的目标是让内容提供者只访问DBHelper类,让UI使用内容提供者进行CRUD操作”——为什么?您是否计划使用其他应用程序通过您的提供商访问此内容?如果不是,那么为什么不放弃提供程序,直接使用SQLite(或者通过Room或ORM层)?纯粹出于内部目的使用
ContentProvider
不是一种流行的方法。