拆轮子系列之理解GreenDao框架源码

GreenDao概述

如果Android项目中要使用GreenDAO框架,需要先创建一个Java项目用于生成实体类和DAO类,然后在Android项目中使用这些类,在此过程中分别需要对Android项目添加GreenDAO的核心包依赖和对Java项目添加generator包依赖,所以解析GreenDAO的源码需要解析两部分,而这里只解析GreenDAO核心包在Android项目中的工作原理,generator包中的原理很简单,总的来说有四个作用:就是用于生成实体类、DAO类、建立多表之间的关联以及配置实体类的接口和序列化功能

在Android项目中用到的最核心的四个类就是:DaoMaster、DaoSession、实体类、实体Dao类。
这四个核心类的功能体系如下图所示:

DaoMaster

GreenDao框架管理类,该类对数据库相关管理操作进行封装
我们知道在使用GreenDAO时候,我们的入口点就是通过DaoMaster的静态内部类DevOpenHelper来创建一个DevOpenHelper对象

DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "students-db", null);

而DevOpenHelper对象又是什么呢?我们都知道在使用SQLite的时候,我们必须通过继承SQLiteOpenHelper类并且实现它内部的一些方法来创建数据库,而这里仅仅通过DevOpenHelper类就成功创建了一个文件名为”students-db”的数据表,那么内部又是怎么实现的呢?我们可以看看DaoMaster类的源码:

public class DaoMaster extends AbstractDaoMaster {
   
   
    public static final int SCHEMA_VERSION = 1;

    /** Creates underlying database table using DAOs. */
    public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
        StudentDao.createTable(db, ifNotExists);
    }

    /** Drops underlying database table using DAOs. */
    public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
        StudentDao.dropTable(db, ifExists);
    }

    public static abstract class OpenHelper extends SQLiteOpenHelper {
   
   

        public OpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory, SCHEMA_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
            createAllTables(db, false);
        }
    }

    /** WARNING: Drops all table on Upgrade! Use only during development. */
    public static class DevOpenHelper extends OpenHelper {
   
   
        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }

    public DaoMaster(SQLiteDatabase db) {
        super(db, SCHEMA_VERSION);
        registerDaoClass(StudentDao.class);
    }

    public DaoSession newSession() {
        return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
    }

    public DaoSession newSession(IdentityScopeType type) {
        return new DaoSession(db, type, daoConfigMap);
    }

}

从DaoMaster中我们可以发现,DaoMaster除了具有创建表和删除表的两个功能外,还有两个内部类,分别为OpenHelper和DevOpenHelper,OpenHelper继承于SQLiteOpenHelper用于创建所有的数据库表;DevOpenHelper继承于OpenHelper用于数据库升级,而重写的onCreate()方法中调用了createAllTables(db,false);方法来创建数据表,而createAllTables()方法中是通过调用StudentDao静态方法来创建表的StudentDao.createTable(db, ifNotExists);我们点进这个方法中去看个究竟

public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"STUDENT\" (" + //
                "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
                "\"NAME\" TEXT NOT NULL ," + // 1: name
                "\"AGE\" INTEGER," + // 2: age
                "\"IS_MAN\" INTEGER);"); // 3: is_man
    }

发现它内部就是通过sql语句来创建表的,只不过GreenDAO帮我们封装好了,而且你会发现删除表其实也一样:

public static void dropTable(SQLiteDatabase db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"STUDENT\"";
        db.execSQL(sql);
    }

好了,现在我们知道了通过DevOpenHelper是怎么创建表的,而细心的同学会发现在DevOpenHelper类中实现了onUpgrade()方法,就是更新数据库的方法,它在更新数据表的时候会把以前的数据表删除后再重新创建,所以这个你必须注意,当我们在利用GreenDAO更新数据表的时候,如果你想以前表中的数据保存下来的话,我们必须自己封装一个方法。

接下来就是newSession()方法了,这个当然就是得到DaoSession实例了,关于DaoSession实例,GreenDAO官方建议不要重新创建新的实例,保持一个单例的引用即可。好了,DaoMaster源码看完了,接下来就是看它的父类AbstractDaoMaster的源码了,它的源码如下:

public abstract class AbstractDaoMaster {
   
   
    protected final SQLiteDatabase db;
    protected final int schemaVersion;
    protected final Map<Class<? extends AbstractDao<?, ?>>, DaoConfig> daoConfigMap;

    public AbstractDaoMaster(SQLiteDatabase db, int schemaVersion) {
        this.db = db;
        this.schemaVersion = schemaVersion;

        daoConfigMap = new HashMap<Class<? extends AbstractDao<?, ?>>, DaoConfig>();
    }

    protected void registerDaoClass(Class<? extends AbstractDao<?, ?>> daoClass) {
        DaoConfig daoConfig = new DaoConfig(db, daoClass);
        daoConfigMap.put(daoClass, daoConfig);
    }

    public int getSchemaVersion() {
        return schemaVersion;
    }

    /** Gets the SQLiteDatabase for custom database access. Not needed for greenDAO entities. */
    public SQLiteDatabase getDatabase() {
        return db;
    }

    public abstract AbstractDaoSession newSession();

    public abstract AbstractDaoSession newSession(IdentityScopeType type);
}

看这个类的代码,其中最让我们受关注的无非就是这一行了

protected final Map<Class<? extends AbstractDao<?, ?>>, DaoConfig> daoConfigMap;

这里定义了一个Map集合,Key是继承自AbstractDao类的字节码对象,Value则为DaoConfig对象。每个AbstractDao对应着一个DaoConfig,然后保存在Map< Class

protected void registerDaoClass(Class<? extends AbstractDao<?, ?>> daoClass) {
        DaoConfig daoConfig = new DaoConfig(db, daoClass);
        daoConfigMap.put(daoClass, daoConfig);
    }

所以Map的功能现在很清楚了,就是为每一个EntityDao字节码对象建立与之对应的db数据库的映射关系,从而管理所有的EntityDao类。而这个方法在哪里调用了呢?我们回到DaoMaster的源码中,发现在DaoMaster类的构造方法中调用了,并且传入了Student.class,所以我们在创建DaoMaster对象的时候也同时为EntityDao类和相应的数据库db建立好了关联。

DaoSession

从上面可知DaoSession对象是通过master.newSession();创建的。DaoSession对象是连接GreenDao框架到SQLite数据库的纽带,通过该对象我们可以得到一个与数据库某个表相关的操作对象xxxDao。我们看看DaoSession源码,发现它也有一个抽象的父类AbstractDaoSession,我们来看看DaoSession的源码:

public class 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值