前言
之前开发app的时候,用到数据库都是自己封装;这次就想偷个懒,用用框架,各种比较后选择用GreenDAO。 GreenDAO Github代码地址 Android数据库GreenDao使用说明
参照说明添加了依赖、实体类,Make Project后,发现自动生成的代码只能支持一个数据库文件,但是我需要创建多个数据库。
解决方案
简单来说,就是不同的库创建不同的OpenHelper。下面以两个库为例
参照自动生成代码,写两个OpenHelper,直接上代码
public class OrderDbHelper extends DatabaseOpenHelper {
public static final int SCHEMA_VERSION = 6;
public static void createAllTables(Database db, boolean ifNotExists) {
OrderDao.createTable(db, ifNotExists);
ProductDao.createTable(db, ifNotExists);
}
public static void dropAllTables(Database db, boolean ifExists) {
OrderDao.dropTable(db, ifExists);
ProductDao.dropTable(db, ifExists);
}
public OrderDbHelper(Context context, String name) {
super(context, name, SCHEMA_VERSION);
}
@Override
public void onCreate(Database db) {
createAllTables(db, true);
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
if (oldVersion < newVersion) {
dropAllTables(db, true);
onCreate(db);
}
}
}
public class UserDbHelper extends DatabaseOpenHelper {
public static final int SCHEMA_VERSION = 5;
public static void createAllTables(Database db, boolean ifNotExists) {
UserDao.createTable(db, ifNotExists);
}
public static void dropAllTables(Database db, boolean ifExists) {
UserDao.dropTable(db, ifExists);
}
public UserDbHelper(Context context, String name) {
super(context, name, SCHEMA_VERSION);
}
@Override
public void onCreate(Database db) {
createAllTables(db, true);
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
if (oldVersion < newVersion) {
dropAllTables(db, true);
onCreate(db);
}
}
}
然后写一个DbManager
public class DbManager {
private DaoMaster mOrderDaoMaster;
private DaoSession mOrderDaoSession;
private DaoMaster mUserDaoMaster;
private DaoSession mUserDaoSession;
private DbContext mContext;
private DbManager() {
}
private static class SingletonInstance {
private static DbManager INSTANCE = new DbManager();
}
public static DbManager getInstance() {
return SingletonInstance.INSTANCE;
}
public void init(DbContext context) {
mContext = context;
createOrderDb(context, "order.db");
createUserDb(context, "user.db");
}
private void createOrderDb(Context context, String name) {
OrderDbHelper openHelper = new OrderDbHelper(context, name);
mOrderDaoMaster = new DaoMaster(openHelper.getWritableDb());
mOrderDaoSession = mOrderMaster.newSession();
}
private void createUserDb(Context context, String name) {
UserDbHelper openHelper = new UserDbHelper(context, name);
mUserDaoMaster = new DaoMaster(openHelper.getWritableDb());
mUserDaoSession = mUserDaoMaster.newSession();
}
public void insertUser(User user) {
mUserDaoSession.getUserDao().insert(user);
}
public void insertOrder(Order order) {
mOrderDaoSession.getOrderDao().insert(order);
}
public void close() {
closeOrderDb();
closeUserDb();
}
private void closeOrderDb() {
if (mOrderDaoSession != null) {
mOrderDaoSession.clear();
mOrderDaoSession = null;
}
if (mOrderDaoMaster != null) {
mOrderDaoMaster.getDatabase().close();
mOrderDaoMaster = null;
}
}
private void closeUserDb() {
if (mUserDaoSession != null) {
mUserDaoSession.clear();
mUserDaoSession = null;
}
if (mUserDaoMaster != null) {
mUserDaoMaster.getDatabase().close();
mUserDaoMaster = null;
}
}
}
当然,偷懒是有代价的,这里利用的框架生成的 DaoMaster和DaoSession,每个库都会创建对应的对象,而框架生成的代码中是包含了所有实体的,这会造成内存的浪费,比如DaoMaster的构造函数
public DaoMaster(Database db) {
super(db, SCHEMA_VERSION);
registerDaoClass(UserDao.class);
registerDaoClass(OrderDao.class);
registerDaoClass(ProductDao.class);
}
可以看出,第一个库其实是不需要注册UserDao的,第二个库是不需要OrderDao和ProductDao的。同样,DaoSession也有类似问题。 勤快的同学可以去掉框架自动生成代码,每个库都编写自己的DaoMaster和DaoSession,但这样就不能偷懒了,每次添加实体或者修改都是挺麻烦的事情。
期待GreenDAO早日改进,或者各位有什么更好的解决方案,希望能回复一下。
修改数据库文件存储路径
本项目中,还希望修改一下数据库文件存储路径。上面代码中也看到了,有个DbContext,其实是自己实现的,继承自ContextWrapper,重写getDatabasePath方法。当然也可以在初始化Context中,重写这个方法来修改数据文件路径。
public class DbContext extends ContextWrapper {
public DbContext(Context base) {
super(base);
}
@Override
public File getDatabasePath(String name) {
return new File(getExternalFilesDir("databases"), name);
}
}
最后
在研究多库方案的时候,看到一个多schema的概念,不知道这个schema该怎么理解,希望知道的朋友能告知一下,谢谢
|