ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
题外话,这篇博客和之前的博客差这么长时间,是因为我来北京实习了。但是,实习归实习,学习不能停止不是么。在目前所做的东西当中,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://box.kancloud.cn/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://box.kancloud.cn/2016-04-08_5707680881c2d.jpg "") 方法很多啊,我承认我数据库忘的差不多了,不过我们可以知道的是,这么多的方法是为了让我们拼接出一条完整的sql语句。可以看到其中的as or and where 等等都是sql语句中一个关键子,最后带哦用execXXXX就可以到查询了。这里的代码就不给大家分析了。 ### 总结 总的来说,ActiveAndroid用起来还是很简单的,更多的用法还是看官方的文档吧,[文档地址](https://github.com/pardom/ActiveAndroid/wiki/Getting-started) 到现在我也看来很多的开源框架的源代码了,感觉自己的技术并没有得到很好的提升,在坐的小伙伴有什么好的办法,还希望你们能告诉我。