了解Android.com的“在SQL数据库中保存数据”教程

时间:2015-06-29 10:58:23

标签: android android-sqlite

我正在阅读本教程:http://developer.android.com/training/basics/data-storage/databases.html并提出了很多问题。

这是我在遵循教程时所做的代码:

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;

public final class SongDbHelper extends SQLiteOpenHelper {
    // If you change the database schema, you must increment the database version.
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "Song.db";
    private static final String TEXT_TYPE = " TEXT";
    private static final String PRIMARY_KEY_TYPE = " INTEGER PRIMARY KEY";
    private static final String COMMA_SEP = ",";
    private static final String SQL_CREATE_ENTRIES =
            "CREATE TABLE " + SongEntry.TABLE_NAME + " (" +
                    SongEntry._ID + PRIMARY_KEY_TYPE + COMMA_SEP +
                    SongEntry.COLUMN_NAME_SONG_TITLE + TEXT_TYPE + COMMA_SEP +
                    SongEntry.COLUMN_NAME_ENGLISH_LYRICS + TEXT_TYPE + COMMA_SEP +
                    SongEntry.COLUMN_NAME_ROMAJI_LYRICS + TEXT_TYPE + COMMA_SEP +
                    SongEntry.COLUMN_NAME_KANJI_LYRICS + TEXT_TYPE + COMMA_SEP +
                    SongEntry.COLUMN_NAME_INFO + TEXT_TYPE +
            " )";
    private static final String SQL_DELETE_ENTRIES =
            "DROP TABLE IF EXISTS " + SongEntry.TABLE_NAME;

    public SongDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_ENTRIES);
    }
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // This database is only a cache for online data, so its upgrade policy is
        // to simply to discard the data and start over
        db.execSQL(SQL_DELETE_ENTRIES);
        onCreate(db);
    }
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }


    public static abstract class SongEntry implements BaseColumns {
        public static final String TABLE_NAME = "Song";
        public static final String COLUMN_NAME_SONG_TITLE = "song_title";
        public static final String COLUMN_NAME_ENGLISH_LYRICS = "english_lyrics";
        public static final String COLUMN_NAME_ROMAJI_LYRICS = "romaji_lyrics";
        public static final String COLUMN_NAME_KANJI_LYRICS = "kanji_lyrics";
        public static final String COLUMN_NAME_INFO = "info";

    }
}
  1. 每次应用打开时我们都应该致电SongDbHelper.onCreate()吗? (我想把它放在我的主要活动的onCreate()方法中。

  2. 如果您多次拨打SongDbHelper.onCreate(),是否会重新创建该表,或者SongDbHelper.onCreate()是否会默默无声地失败?

  3. 为什么应用程序需要调用SongDbHelper.onCreate()?如果我把我的应用程序放在应用程序商店,我不会让人们下载我已填充数据的数据库吗?

  4. 在我的应用中何时/何处拨打SongDbHelper.onUpgrade()?我认为当用户注意到“此应用程序有可用更新。点击此处下载”或类似内容时会发生这种情况。我只是感到困惑,因为我想用户只需下载一个.db文件,数据库完好无损;因此无需致电SongDbHelper.onCreate()

  5. 如果应用必须调用SongDbHelper.onCreate(),它如何用值填充数据库?我认为如果我还有填充值的代码,它会破坏数据库的目的,因为这样的值会被重复(在代码数据库中)。

  6. 使用值填充数据库的最佳方法是什么?使用终端,或以编程方式在应用程序的单独程序中,或仅在Android应用程序中?

3 个答案:

答案 0 :(得分:1)

您的SongDbHelper类应该实现为Singleton实例。

在Application类中实例化它并为所有应用程序公开SongDbHelper对象可能是一个好习惯

public class YourApp extends Application {
   public SongDbHelper songDBHelper;

   @Override
   public void onCreate() {
     super.onCreate();
     songDBHelper = new SongDbHelper(.....);
   }
   public SongDBHelper getSongDB() {
     return songDBHelper;
   }
}

答案 1 :(得分:1)

首先,我建议您再次阅读本教程以了解它。现在继续你的问题,

1)你永远不会打电话给onCreate()。正如您所看到的,它来自超级类 SQLiteOpenHelper ,它是由系统调用的,而不是第一次安装应用程序时的调用。

2)因此,从上一个问题中你可以理解,不存在多次调用onCreate()的问题。当用户第一次安装应用程序时,系统将仅调用一次来创建数据库

3)正如你所说,它不会以这种方式运作。当应用程序安装时,将调用onCreate()来创建数据库。之后,您可以使用逻辑将数据填充到其中。 无论如何,都不会从任何地方下载的预定义数据。

4)不,它也不像“每当用户获得更新”时。 onUpgrade()仅在数据库版本更改时调用。如果要更改Play商店中已存在的应用程序上的数据库架构,则可以更改版本号并执行升级适当地在onUpgrade()。

5)你的问题不明确。

我希望在阅读完这个答案后你的观念会有所改变。如果您有其他问题,请再次阅读教程以获得正确的概念或发布新问题。

<强>更新

5)您正在考虑使用之前的歌词创建一个数据库并将其放入您的应用程序中。这就是你对onCreate()产生误解的原因。

请注意,当用户第一次安装应用程序时,将调用onCreate()并创建具有给定架构的数据库。里面没有内容。

要在其中放置内容,您需要以编程方式将行插入到该表中。希望它现在不会破坏目的。

6)现在就你的用例而言。

根据我的说法,最好的解决方案是将所有歌词放在您的网络服务器中,并在您的应用程序中获取这些歌词并将其放入数据库中。

当用户安装应用程序并第一次运行时,您应该查询Web服务器以检查可用的歌词,然后逐个获取它们并使用insert()方法将它们放入数据库中。

注意 - onCreate()只创建一个空白表,并且不会将任何值放入其中。但是您以编程方式将内容放入数据库中,就像使用insert()方法的歌词一样。

现在,当有一些新歌出现时,只需将歌词放入您的服务器,该应用程序将自动查询服务器以检查是否有新的歌词可用并下载并相应地插入数据库。

希望你现在清楚了。

答案 2 :(得分:1)

回答:

第1,2,3点:正如您在this link关注的教程中所提到的,我们不应该致电SongDbHelper.onCreate()。而不是它,当我们想要从 Helper类引用数据库时,我们使用 CONSTUCTOR ,如:

SongDbHelper mDbHelper = new SongDbHelper(getContext());
// this will call super method internally and
// this will create table in database

第4点:onUpgrade()对我们的责任也不是明确的。当我们更改数据库模式时,我们更新DATABASE_VERSION并且android框架将在内部为我们调用onUpgrade()

第5点:您可以从xmldatabase逐个存储歌词。据我所知,这是正确的方法

更新:

最好的方法是在{strong>之前,store your database并让应用然后读/写的网络服务器上download it from the web server servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Development"); 进入数据库。这个不会破坏数据库的目的,此外它不会复制数据库条目和代码条目(xml)。除此之外,您的应用程序大小也将更小,因为应用程序将在运行时下载数据库,而不是最初存储在设备内存中