了解 Android.com 的 "Saving Data in SQL Databases" 教程
Understanding Android.com's "Saving Data in SQL Databases" Tutorial
我正在阅读这个教程: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";
}
}
我们是否应该在每次打开应用程序时调用 SongDbHelper.onCreate()
? (我想把它放在我的主要 activity 的 onCreate()
方法中。
如果您多次调用 SongDbHelper.onCreate()
,它会重新创建 table,还是 SongDbHelper.onCreate()
会安静而优雅地失败?
为什么应用程序仍然需要调用 SongDbHelper.onCreate()
?如果我把我的应用程序放到应用程序商店,我不会让人们下载我已经填满数据的数据库吗?
When/where 在我的应用程序中调用 SongDbHelper.onUpgrade()
?我假设当用户注意到 "There is an update available for this app. Click here to download it" 或类似的东西时会发生这种情况。我只是很困惑,因为我想用户只是下载了一个数据库完好的 .db
文件;因此不需要调用 SongDbHelper.onCreate()
.
如果应用程序必须调用 SongDbHelper.onCreate()
,它如何用值填充数据库?我认为如果我也有填充值的代码,这将破坏数据库的目的,因为那样的话值将被复制(在代码 和 数据库中)。
用值填充数据库的最佳方法是什么?使用终端,或以编程方式在与应用程序分开的程序中,或仅在 Android 应用程序中?
您的 SongDbHelper class 应该作为 Singleton 实例实现。
最好在您的应用程序中实例化它 class 并为您的所有应用公开 SongDbHelper 对象
public class YourApp extends Application {
public SongDbHelper songDBHelper;
@Override
public void onCreate() {
super.onCreate();
songDBHelper = new SongDbHelper(.....);
}
public SongDBHelper getSongDB() {
return songDBHelper;
}
}
首先,我建议您再次阅读教程以了解它。现在开始回答您的问题,
1) 你永远不会调用 onCreate() 。如您所见,它来自超级 class SQLiteOpenHelper 并且在应用程序首次安装时由系统而不是您调用。
2) 所以从上一个问题可以看出,不存在多次调用onCreate()的问题。当用户第一次安装应用程序时,系统会只调用一次来创建数据库。
3) 你说的这种方式不行。当应用程序安装时,将调用 onCreate() 来创建数据库。之后,您可以使用您的逻辑将数据填充到其中。 不会像您所说的那样从任何地方下载预定义数据。
4) 不,也不是那样"whenever the users get an update"。 onUpgrade() 仅在数据库版本更改时调用。 如果您想更改 Play 商店中已存在的应用程序的数据库架构,您可以更改版本号和在 onUpgrade() 中适当地执行升级。
5) 你的问题不清楚。
希望看完这篇回答你的观念会有所改变。请再次阅读教程以获得正确的概念,或者 post 如果您还有其他问题,请提出一个新问题。
更新
5) 你正在考虑用以前的歌词创建一个数据库并将其放入你的应用程序中。这就是您对 onCreate() 有误解的原因。
请注意,当用户首次安装应用程序时,将调用 onCreate() 并创建具有给定架构的数据库。里面不会有内容。
要将内容放入其中,您需要以编程方式向其中插入行 table。希望它现在不会破坏目的。
6) 现在关于您的用例。
根据我的说法,最好的解决方案是将您所有的歌曲歌词放在您的网络服务器中,然后在您的应用程序中获取这些歌词并将其放入数据库中。
当用户第一次安装并运行应用程序时,您应该查询网络服务器以检查可用的歌词,然后使用 insert() 方法将它们逐一获取并放入您的数据库中。
注意 - onCreate() 只是创建一个空白 table 并且没有将任何值放入其中。但是您是以编程方式将内容放入数据库中,例如使用 insert() 方法的歌词。
现在每当有新歌出现时,只需将歌词放入您的服务器,应用程序将自动查询服务器以检查是否有任何新歌曲歌词可用并下载并相应地插入到数据库中。
希望你现在清楚了。
回答:
第 1、2、3 点:正如您在 this link 关注的教程中简单提到的,我们不应该调用 SongDbHelper.onCreate()
。相反,当我们想从 Helper class 获取数据库的引用时,我们使用 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 : 您可以将歌词从 xml
中一首一首地存储到 database
中。据我所知这是正确的方法
更新:
最好的方法是 store your database
在 prior、download it from the web server
的 Web 服务器上 store your database
然后让应用程序 read/write 进入数据库。这不会破坏数据库的目的,此外它不会重复数据库条目和代码条目(xml)。除此之外,您的应用程序大小也会更小,因为应用程序将在运行时下载数据库,而不是最初存储在设备内存中
我正在阅读这个教程: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";
}
}
我们是否应该在每次打开应用程序时调用
SongDbHelper.onCreate()
? (我想把它放在我的主要 activity 的onCreate()
方法中。如果您多次调用
SongDbHelper.onCreate()
,它会重新创建 table,还是SongDbHelper.onCreate()
会安静而优雅地失败?为什么应用程序仍然需要调用
SongDbHelper.onCreate()
?如果我把我的应用程序放到应用程序商店,我不会让人们下载我已经填满数据的数据库吗?When/where 在我的应用程序中调用
SongDbHelper.onUpgrade()
?我假设当用户注意到 "There is an update available for this app. Click here to download it" 或类似的东西时会发生这种情况。我只是很困惑,因为我想用户只是下载了一个数据库完好的.db
文件;因此不需要调用SongDbHelper.onCreate()
.如果应用程序必须调用
SongDbHelper.onCreate()
,它如何用值填充数据库?我认为如果我也有填充值的代码,这将破坏数据库的目的,因为那样的话值将被复制(在代码 和 数据库中)。用值填充数据库的最佳方法是什么?使用终端,或以编程方式在与应用程序分开的程序中,或仅在 Android 应用程序中?
您的 SongDbHelper class 应该作为 Singleton 实例实现。
最好在您的应用程序中实例化它 class 并为您的所有应用公开 SongDbHelper 对象
public class YourApp extends Application {
public SongDbHelper songDBHelper;
@Override
public void onCreate() {
super.onCreate();
songDBHelper = new SongDbHelper(.....);
}
public SongDBHelper getSongDB() {
return songDBHelper;
}
}
首先,我建议您再次阅读教程以了解它。现在开始回答您的问题,
1) 你永远不会调用 onCreate() 。如您所见,它来自超级 class SQLiteOpenHelper 并且在应用程序首次安装时由系统而不是您调用。
2) 所以从上一个问题可以看出,不存在多次调用onCreate()的问题。当用户第一次安装应用程序时,系统会只调用一次来创建数据库。
3) 你说的这种方式不行。当应用程序安装时,将调用 onCreate() 来创建数据库。之后,您可以使用您的逻辑将数据填充到其中。 不会像您所说的那样从任何地方下载预定义数据。
4) 不,也不是那样"whenever the users get an update"。 onUpgrade() 仅在数据库版本更改时调用。 如果您想更改 Play 商店中已存在的应用程序的数据库架构,您可以更改版本号和在 onUpgrade() 中适当地执行升级。
5) 你的问题不清楚。
希望看完这篇回答你的观念会有所改变。请再次阅读教程以获得正确的概念,或者 post 如果您还有其他问题,请提出一个新问题。
更新
5) 你正在考虑用以前的歌词创建一个数据库并将其放入你的应用程序中。这就是您对 onCreate() 有误解的原因。
请注意,当用户首次安装应用程序时,将调用 onCreate() 并创建具有给定架构的数据库。里面不会有内容。
要将内容放入其中,您需要以编程方式向其中插入行 table。希望它现在不会破坏目的。
6) 现在关于您的用例。
根据我的说法,最好的解决方案是将您所有的歌曲歌词放在您的网络服务器中,然后在您的应用程序中获取这些歌词并将其放入数据库中。
当用户第一次安装并运行应用程序时,您应该查询网络服务器以检查可用的歌词,然后使用 insert() 方法将它们逐一获取并放入您的数据库中。
注意 - onCreate() 只是创建一个空白 table 并且没有将任何值放入其中。但是您是以编程方式将内容放入数据库中,例如使用 insert() 方法的歌词。
现在每当有新歌出现时,只需将歌词放入您的服务器,应用程序将自动查询服务器以检查是否有任何新歌曲歌词可用并下载并相应地插入到数据库中。
希望你现在清楚了。
回答:
第 1、2、3 点:正如您在 this link 关注的教程中简单提到的,我们不应该调用 SongDbHelper.onCreate()
。相反,当我们想从 Helper class 获取数据库的引用时,我们使用 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 : 您可以将歌词从 xml
中一首一首地存储到 database
中。据我所知这是正确的方法
更新:
最好的方法是 store your database
在 prior、download it from the web server
的 Web 服务器上 store your database
然后让应用程序 read/write 进入数据库。这不会破坏数据库的目的,此外它不会重复数据库条目和代码条目(xml)。除此之外,您的应用程序大小也会更小,因为应用程序将在运行时下载数据库,而不是最初存储在设备内存中