Android ORM框架之-ActiveAndroid的简

题外话,这篇博客和之前的博客差这么长时间,是因为我来北京实习了。但是,实习归实习,学习不能停止不是么。在目前所做的东西当中,ORM框架用的是ActiveAndroid,以前我写过GreenDao的,那么现在就来记录下ActiveAndroid的吧。github地址, 这一篇文章就不在多说如何使用了,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用起来还是很简单的,更多的用法还是看官方的文档吧,文档地址

到现在我也看来很多的开源框架的源代码了,感觉自己的技术并没有得到很好的提升,在坐的小伙伴有什么好的办法,还希望你们能告诉我。

文章导航