題外話,這篇博客和之前的博客差這么長時間,是因為我來北京實習了。但是,實習歸實習,學習不能停止不是么。在目前所做的東西當中,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);
~~~
我這里只是設置了下數據庫名和版本號,當然也可以設置其他東西,如下圖。

有緩存大小,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類。

方法很多啊,我承認我數據庫忘的差不多了,不過我們可以知道的是,這么多的方法是為了讓我們拼接出一條完整的sql語句。可以看到其中的as or and where 等等都是sql語句中一個關鍵子,最后帶哦用execXXXX就可以到查詢了。這里的代碼就不給大家分析了。
### 總結
總的來說,ActiveAndroid用起來還是很簡單的,更多的用法還是看官方的文檔吧,[文檔地址](https://github.com/pardom/ActiveAndroid/wiki/Getting-started)
到現在我也看來很多的開源框架的源代碼了,感覺自己的技術并沒有得到很好的提升,在坐的小伙伴有什么好的辦法,還希望你們能告訴我。
- 前言
- Android四大圖片緩存框架之-Fresco(一)
- Android四大圖片緩存框架之-Fresco之initialize(二)
- Android 四大緩存框架之-Universal-Image-Loader
- Android四大圖片緩存框架之-Picasso和Glide
- Android ORM數據庫框架之-greenDao(一)
- Android ORM數據庫框架之-greenDao(二)
- Android ORM數據庫框架之-greenDao(三)
- Android ORM數據庫框架之-greenDao(四)
- Android 網絡開源庫之-retrofit
- RxJava的簡單學習(學習自扔物線)
- Android ORM框架之-ActiveAndroid的簡單分析