【问题标题】:Is it really necessary to create SQLite tables every time the application starts?每次应用程序启动时是否真的需要创建 SQLite 表?
【发布时间】:2012-03-29 04:37:27
【问题描述】:

我在不止一个 SQLite 教程中注意到,该表是在扩展 SQLiteOpenHelper 的类的 onCreate() 事件中重新创建的。在 Firefox 插件的帮助下,我已经在 Android 环境 (Eclipse IDE) 之外创建了我的 SQLite 数据库和表。数据库表位于预期位置:

C:\aXX3&Space\Android\workspace\OnDemandAndAutomatic_Project\assets

每次我都必须以编程方式重新创建它们,这对我来说似乎很奇怪(显然,它们继续存在并保留数据,或者有什么意义)?但是,我现在对这个应用程序有一个严重的问题,这让我想到了我的问题:

  • 真的有必要每次都提醒Android关于数据库吗?

令我懊恼的是,我刚刚意识到,我没有在 C:\aXX3&Space\Android\workspace\OnDemandAndAutomatic_Project\assets 中创建我的数据库表,而是将它们放在 C:\aXX3&Space\Android\workspace\OnDemandAndAutomatic\assets 中,这是应用程序的早期版本,但将 SQLite 文件复制到正确的位置一点都没有改变。如果这是导致问题的原因,因为我的应用程序正在寻找一个 AWOL 数据库,那么简单地复制和粘贴文件是否还不够?我必须对正式做点什么吗 将数据库引入system/Android/Eclipse 目录?有什么建议吗?

【问题讨论】:

    标签: android sqliteopenhelper android-sqlite


    【解决方案1】:

    我认为你在这里误解了。构造SQLiteOpenHelper对象时,会检查SQLite数据库是否存在,如果不存在,会调用其onCreate()方法(一般开发者实现创建数据库SQL的地方)

    更新:
    @Clay Shannon:我将解释 Eclipse 和 Android 项目的工作机制。假设您使用 Eclipse 来编写 Android 项目。新项目将在工作区中创建一个项目文件夹(在您的情况下,它是 C:\aXX3&Space\Android\workspace,项目文件夹是 OnDemandAndAutomatic_Project )。这个文件夹会包含几个子文件夹如:src、bin、assets、res、...每个文件夹都有自己的作用,你对assets文件夹感兴趣吧? Assets 文件夹用于包含参考文件(不能或您不想放在 res 文件夹中),例如:html 文件、声音文件、图像文件、文本文件......当 Eclipse 从项目构建 apk 时,这些文件也包含在 apk 中。当您在 Android 设备上安装 apk 时,会将 apk 复制到 Android 系统文件夹中,并创建一个包含应用程序数据的文件夹,如 Dharmendra 所述:/data/data/{packagename}/ em>(包名,如 com.google.app 等,此路径适用于您设备的 Android 操作系统,不适用于 Windows)。

    你的情况是你想使用你已经存在的数据库,所以你需要实现一个函数来检查你的数据库是否存在,如果不复制你的数据库到数据库路径 /data/data/ {packagename}/databases/,并在您的应用启动时调用该函数。如何做到这一点已经在这里How to copy existing database from one app to another 回答。另外这里是访问资产文件的参考,以防您不知道http://www.wiseandroid.com/post/2010/06/14/Android-Beginners-Intro-to-Resources-and-Assets.aspx

    希望现在您可以解决您的问题。 注意:您已经存在的数据库必须是SQLite数据库,否则即使您复制到正确的路径,应用程序也无法识别它。

    【讨论】:

    • 啊;现在说得通了。但直觉?我想不是。谁会想到 OnCreate() 事件是有条件的?
    • 好的,我更新了答案。希望您现在可以解决您的问题
    • 好的,所以我不应该期望在我的开发机器上找到 /data/data// 文件夹(Windows);这解释了它。谢谢。
    【解决方案2】:

    实际上SQLiteOpenHelper 负责您的数据库创建、升级等等。 如果要以编程方式创建表,则必须在 SQLiteOpenHelper 类的 onCreate 方法中编写创建表查询。如果要在先前创建的数据库之后更新数据库,则只能在 onUpgrade 方法中编写修改后的表查询您将不得不更改数据库版本。

    如果您已经在外部创建了一个数据库并且想要使用该数据库,那么您必须将该数据库放在 assets 文件夹中,并将该文件复制到位于 /data/data/packagename/databases 文件夹中的数据库文件夹中。

    这里是将数据库从资产复制到数据库文件夹的示例

    private static boolean copyDataBase(Context c) throws IOException {
        String DB_PATH = "/data/data/" + c.getPackageName() + "/databases/";
        AssetManager mg = c.getResources().getAssets();
        InputStream myInput = null;
    
        try {
            myInput = mg.open(DATABASE_NAME);
    
        } catch (IOException ex) {
            return false;
        }
    
        if (myInput != null) {
            String outFileName = DB_PATH + DATABASE_NAME;
            OutputStream myOutput = new FileOutputStream(outFileName);
            byte[] buffer = new byte[8000];
            int length;
    
            while ((length = myInput.read(buffer)) > 0) {
                myOutput.write(buffer, 0, length);
            }
            myOutput.flush();
            myOutput.close();
            myInput.close();
    
            Log.d(TAG, "Database is copied");
            return true;
        }
        return false;
    }
    

    这是检查数据库及其副本的方法

    public void copyDatabase() {
    
        try {
            SharedPreferences preferences = c.getSharedPreferences(c.getPackageName(), Context.MODE_PRIVATE);
            if (checkDataBase(c)) {
                if (preferences.getInt("dbversion", 0) != 0) {
                    c.deleteDatabase(DatabaseHelper.DATABASE_NAME);
                }
    
            }
            getReadableDatabase();
            close();
            if (copyDataBase(c)) {
                Editor editor = preferences.edit();
                editor.putInt("dbversion", DatabaseHelper.DATABASE_VERSION);
                editor.commit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    这里是检查数据库是否已经存在的例子?

    public static boolean checkDataBase(Context c) {
        File f = new File("/data/data/" + c.getPackageName() + "/databases/"
                + DATABASE_NAME);
        if (!f.exists())
            return false;
        SQLiteDatabase checkDB = null;
        try {
            checkDB = SQLiteDatabase
                    .openDatabase("/data/data/" + c.getPackageName()
                            + "/databases/" + DATABASE_NAME, null,
                            SQLiteDatabase.OPEN_READONLY);
            checkDB.close();
        } catch (SQLiteException e) {
            e.printStackTrace();
        }
        return checkDB != null ? true : false;
    }
    

    【讨论】:

    • 啊哈!最后一个可能是我的问题 - 我只在资产文件夹中拥有它。
    • 我在我的 HD 中搜索“data\data\”(Windows 7),但一无所获。这是我需要自己创建的目录结构吗?如果是这样,它与我的资产文件夹的关系到底应该在哪里,其路径是:C:\aXX3&Space\Android\workspace\OnDemandAndAutomatic_Project\assets?
    • 如果您已经创建了数据库,则将数据库复制到资产文件夹,当应用程序启动时,将数据库从资产文件夹复制到您的数据库文件夹,您可以从 DDMS => 文件资源管理器中找到。在文件资源管理器中有一个目录结构,如 data/data/{packagename}/databases。可能你找不到数据库文件夹,因为你还没有创建数据库,所以首先创建一个文件夹,然后将你的数据库复制到数据库文件夹。
    • "这是从资产复制数据库到数据库文件夹的示例" - 有必要吗?当您的 app/.apk 安装在设备上时,Android [子] 系统不会自动为您执行此操作吗?
    • 是的,我已经使用 Firefox 插件创建了数据库和表;它/它们存在于 /assets 文件夹中。
    【解决方案3】:

    如果数据库不存在,SQLiteOpenHelper 将调用其onCreate()。如果数据库模式已更改并需要升级,则调用 onUpgrade()。因此,您的问题的答案是:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-02
      相关资源
      最近更新 更多