我的Android应用需要一个本地数据库。哪种方式最好?我该使用哪个类子类,子类,重新实现等。我在网上找到了太多的信息,但我仍然不知道哪些是最佳做法。
这是一个相当广泛的问题,取决于您的经验和使用水平。
但是通常的做法是创建自己的ContentProvider
,用来抽象数据库访问。这样,您可以使用Uri
来执行选择/更新/删除/插入查询。
对于SQLite数据库本身,请使用SQLiteOpenHelper
来抽象创建和升级SQLite数据库。这将使您能够轻松地升级您的数据库,而不会让用户失去所有数据。
我可以附上我在以前项目中使用的一段代码,帮助您入门。但是实现整个过程可能超出单个问题/答案的范围。
public class MyServiceProvider extends ContentProvider {
private SQLiteDatabase db;
@Override
public boolean onCreate() {
// Initialize the database and assign it to the private variable
MyDatabaseHelper sqlHelper = new MyDatabaseHelper(getContext());
db = sqlHelper.getReadableDatabase();
return (db == null)?false:true;
}
@override
Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
// handle the query here, form it, do your checks and then access the DB
db.query(....);
}
}
class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String LOG_TAG = "MyAppTag";
private static final String DB_NAME = "Databasename";
private static final String TABLE_NAME = "Tablename";
private static final int DATABASE_VERSION = 2;
public static MyServiceProvider.CONTENT_URI = Uri.parse("content://com.mycompany.myApp.MyAppService/myTableOrIdentifier");
public MyDatabaseHelper(Context context){
super(context, DB_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE IF NOT EXISTS ....";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Here you can perform updates when the database structure changes
// Begin transaction
db.beginTransaction();
try {
if(oldVersion<2){
// Upgrade database structure from Version 1 to 2
String alterTable = "ALTER ....";
db.execSQL(alterTable);
Log.i(LOG_TAG,"Successfully upgraded to Version 2");
}
// This allows you to upgrade from any version to the next most
// recent one in multiple steps as you don't know if the user has
// skipped any of the previous updates
if(oldVersion<3){
// Upgrade database structure from Version 2 to 3
String alterTable = "ALTER ....";
db.execSQL(alterTable);
Log.i(LOG_TAG,"Successfully upgraded to Version 3");
}
// Only when this code is executed, the changes will be applied
// to the database
db.setTransactionSuccessful();
} catch(Exception ex){
ex.printStackTrace();
} finally {
// Ends transaction
// If there was an error, the database won't be altered
db.endTransaction();
}
}
}
ContentResolver contentResolver = getContentResolver();
...
Cursor c = contentResolver.query(
// The Uri results in content://com.mycompany.myApp.MyAppService/myTableOrIdentifier/someId
Uri.withAppendedPath(MyServiceProvider.CONTENT_URI, someId),
new String[] {
// only get fields we need!
"MyDbFieldIneed"
},
null, null, null);
Cursor
,您可以迭代它并获取结果。这也是Android中大多数事物的实现方式(例如,从地址簿获取地址也是通过Uri和Cursor实现的)。
编辑:
我意识到代码高亮使链接难以看到。这里是您需要的重要类的链接:
编辑2:
如果你处理多个表格,UriMatcher
也是一个重要的资源
https://github.com/TimotheeJeannin/ProviGen
使用起来非常简单。您只需创建一个Contract类,使用注释指示您需要在数据库中使用哪些列,它将自动创建所有内容。我甚至可以在一个数据库中创建多个表。
哪种方式最好?
您需要使用Android自带的SQLite
。每个Android应用程序都可以拥有自己的数据库。
我该使用哪个类子类或重新实现?
您需要扩展SQLiteOpenHelper
类,它确定您的数据库名称、如何升级/降级、表结构等。 它还定义了获取对数据库引用的方法。
是的,有很多资源可供使用,但并非所有资源都友好且质量良好。这里有一些我喜欢的:
Lars Vogel的SQLite和ContentProvider
Gustin教授的Android教程
至于您的问题标题Android数据库的最佳实践
,我只能说适用于SQL数据库的所有最佳实践也适用于此,例如规范化等。
getContentResolver()
是Context
的一个方法,而Activity
继承自Context
(实际上Activity
继承自ContextThemeWrapper
,后者继承自ContextWrapper
,再后者继承自Context
)。因此,一个简单的ContentResolver contentResolver = getContentResolver();
就可以完成它。 - Tseng