Android ORM框架之-ActiveAndroid的简单分析
最后更新于:2022-04-01 15:49:18
题外话,这篇博客和之前的博客差这么长时间,是因为我来北京实习了。但是,实习归实习,学习不能停止不是么。在目前所做的东西当中,ORM框架用的是ActiveAndroid,以前我写过GreenDao的,那么现在就来记录下ActiveAndroid的吧。[github地址](https://github.com/pardom/ActiveAndroid/), 这一篇文章就不在多说如何使用了,github wiki上面很详细。
### 初始化过程
初始化的过程很简单。我们只需要在Application中调用
~~~
ActiveAndroid.initialize(this);
~~~
就可以完成初始化,(PS:我这里并没有像文档说的一样在配置文件中配置什么的,但是还能用,希望知道的小伙伴指点我一下)。
当然,上面的方法会使用默认的参数来创建出数据库来,我们也可以配置。代码如下
~~~
Configuration configuration = new Configuration.Builder(this)
.setDatabaseName("guilei.db")
.setDatabaseVersion(2)
.create();
ActiveAndroid.initialize(configuration);
~~~
我这里只是设置了下数据库名和版本号,当然也可以设置其他东西,如下图。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-08_570768086e666.jpg "")
有缓存大小,models,类型等等(我们想要转化的类型,如Data)
这里就不在多说了。我们看看ActiveAndroid是如何完成初始化的吧。
~~~
public static void initialize(Configuration configuration, boolean loggingEnabled) {
// Set logging enabled first
setLoggingEnabled(loggingEnabled);
Cache.initialize(configuration);
}
~~~
我们看Cache的initialize方法。
~~~
public static synchronized void initialize(Configuration configuration) {
if (sIsInitialized) {
Log.v("ActiveAndroid already initialized.");
return;
}
sContext = configuration.getContext();
sModelInfo = new ModelInfo(configuration);
sDatabaseHelper = new DatabaseHelper(configuration);
// TODO: It would be nice to override sizeOf here and calculate the memory
// actually used, however at this point it seems like the reflection
// required would be too costly to be of any benefit. We'll just set a max
// object size instead.
sEntities = new LruCache<String, Model>(configuration.getCacheSize());
openDatabase();
sIsInitialized = true;
Log.v("ActiveAndroid initialized successfully.");
}
~~~
我们先来看着一行代码
~~~
sModelInfo = new ModelInfo(configuration);
~~~
我们得看看这是干什么的。这个最终会调用ModelInfo的scanForModel方法,从名字上就知道是扫描Model的。这个方法会扫描dex文件,并调用scanForModelClasses方法,来扫描出继承Model的类,也就是我们的实体类。关键代码如下。
~~~
Class<?> discoveredClass = Class.forName(className, false, classLoader);
if (ReflectionUtils.isModel(discoveredClass)) {
@SuppressWarnings("unchecked")
Class<? extends Model> modelClass = (Class<? extends Model>) discoveredClass;
mTableInfos.put(modelClass, new TableInfo(modelClass));
}
else if (ReflectionUtils.isTypeSerializer(discoveredClass)) {
TypeSerializer instance = (TypeSerializer) discoveredClass.newInstance();
mTypeSerializers.put(instance.getDeserializedType(), instance);
}
~~~
接下来看下面这一行代码,也是非常关键的代码。
~~~
sDatabaseHelper = new DatabaseHelper(configuration)
~~~
~~~
public DatabaseHelper(Configuration configuration) {
super(configuration.getContext(), configuration.getDatabaseName(), null, configuration.getDatabaseVersion());
copyAttachedDatabase(configuration.getContext(), configuration.getDatabaseName());
mSqlParser = configuration.getSqlParser();
}
~~~
看到其中的copyAttachedDatabase了么。这个方法会将Assets目录下的数据库,拷贝到databases目录下。
~~~
final InputStream inputStream = context.getAssets().open(databaseName);
final OutputStream output = new FileOutputStream(dbPath);
byte[] buffer = new byte[8192];
int length;
while ((length = inputStream.read(buffer, 0, 8192)) > 0) {
output.write(buffer, 0, length);
}
~~~
这个类继承只SQLiteOpenHelper,我们看下他的OnCreate方法。
~~~
public void onCreate(SQLiteDatabase db) {
executePragmas(db);
executeCreate(db);
executeMigrations(db, -1, db.getVersion());
executeCreateIndex(db);
}
~~~
继续看executeCreate方法。
~~~
private void executeCreate(SQLiteDatabase db) {
db.beginTransaction();
try {
for (TableInfo tableInfo : Cache.getTableInfos()) {
db.execSQL(SQLiteUtils.createTableDefinition(tableInfo));
}
db.setTransactionSuccessful();
}
finally {
db.endTransaction();
}
}
~~~
这个方法就会把我们扫描出来的Model类转化为数据库。我们看下创建数据表的具体方法。
~~~
public static String createTableDefinition(TableInfo tableInfo) {
final ArrayList<String> definitions = new ArrayList<String>();
for (Field field : tableInfo.getFields()) {
String definition = createColumnDefinition(tableInfo, field);
if (!TextUtils.isEmpty(definition)) {
definitions.add(definition);
}
}
definitions.addAll(createUniqueDefinition(tableInfo));
return String.format("CREATE TABLE IF NOT EXISTS %s (%s);", tableInfo.getTableName(),
TextUtils.join(", ", definitions));
}
~~~
这个方法会将model类中的成员抽成数据表对应的字段。具体的代码我们就不往深处看了。我们看下数据库更新吧。
~~~
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
executePragmas(db);
executeCreate(db);
executeMigrations(db, oldVersion, newVersion);
}
~~~
可以看到,和GreenDao不同的是这里是可以实现数据库更新的。
### CURD 过程
在这里,我以查询为例。来简要的说明一下。
一个简单的查询过程是下面这个样子
~~~
Item result = new Select().from(Item.class).executeSingle();
~~~
Select().from(Model)是要告诉我们从那张表找,接下来的一些列条件则交给Form来负责。
~~~
public From from(Class<? extends Model> table) {
return new From(table, this);
}
~~~
我们去看下From类。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-08_5707680881c2d.jpg "")
方法很多啊,我承认我数据库忘的差不多了,不过我们可以知道的是,这么多的方法是为了让我们拼接出一条完整的sql语句。可以看到其中的as or and where 等等都是sql语句中一个关键子,最后带哦用execXXXX就可以到查询了。这里的代码就不给大家分析了。
### 总结
总的来说,ActiveAndroid用起来还是很简单的,更多的用法还是看官方的文档吧,[文档地址](https://github.com/pardom/ActiveAndroid/wiki/Getting-started)
到现在我也看来很多的开源框架的源代码了,感觉自己的技术并没有得到很好的提升,在坐的小伙伴有什么好的办法,还希望你们能告诉我。