LitePal源码学习(1)——建表流程(创建数据库)

本文详细解析了LitePal库的建表流程,从LitePal.getDatabase()开始,探讨了创建数据库、解析XML配置、生成SQLite表的过程,包括LitePalAttr、LitePalConfig、TableModel、ColumnModel等关键概念,以及如何处理表关联和外键。
摘要由CSDN通过智能技术生成

add 2018/6/11

以上是LitePal的包结构,来自https://blog.csdn.net/android_app_2012/article/details/78025704

我学习的方式是通过使用LItePal的顺序来的。使用LitePal第一步是在asssets写litepal.xml文件,建表操作是LitePal.getDatabase(),那么可以以LitePal为切入点进行学习。

        创建DB的过程:LitePal.getDatabase()

/**
     * Get a writable SQLiteDatabase.
     *
     * @return A writable SQLiteDatabase instance
     */
    public static SQLiteDatabase getDatabase() {
        synchronized (LitePalSupport.class) {
            return Connector.getDatabase();
        }
    }

可以看到这个方法给LitePalSupport加锁,然后调用Connector.getDatabase(),源码如下:

public static SQLiteDatabase getDatabase() {
		return getWritableDatabase();
	}

继续,Connector.getWritableDatabase():

	public synchronized static SQLiteDatabase getWritableDatabase() {
		LitePalOpenHelper litePalHelper = buildConnection();
		return litePalHelper.getWritableDatabase();
	}

LitePalOpenHelper继承自SQLiteOpenHelper,最后调用的getWritableDatabase(),是原生的方法,接下来将关注点放在Connextor.buildConnextion():

/**
	 * Build a connection to the database. This progress will analysis the
	 * litepal.xml file, and will check if the fields in LitePalAttr are valid,
	 * and it will open a SQLiteOpenHelper to decide to create tables or update
	 * tables or doing nothing depends on the version attributes.
	 * 
	 * After all the stuffs above are finished. This method will return a
	 * LitePalHelper object.Notes this method could throw a lot of exceptions.
	 * 
	 * @return LitePalHelper object.
	 * 
	 * @throws org.litepal.exceptions.InvalidAttributesException
	 */
	private static LitePalOpenHelper buildConnection() {
		LitePalAttr litePalAttr = LitePalAttr.getInstance();
		litePalAttr.checkSelfValid();
		if (mLitePalHelper == null) {
			String dbName = litePalAttr.getDbName();
			if ("external".equalsIgnoreCase(litePalAttr.getStorage())) {
				dbName = LitePalApplication.getContext().getExternalFilesDir("") + "/databases/" + dbName;
			} else if (!"internal".equalsIgnoreCase(litePalAttr.getStorage()) && !TextUtils.isEmpty(litePalAttr.getStorage())) {
                // internal or empty means internal storage, neither or them means sdcard storage
                String dbPath = Environment.getExternalStorageDirectory().getPath() + "/" + litePalAttr.getStorage();
                dbPath = dbPath.replace("//", "/");
                if (BaseUtility.isClassAndMethodExist("android.support.v4.content.ContextCompat", "checkSelfPermission") &&
                        ContextCompat.checkSelfPermission(LitePalApplication.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    throw new DatabaseGenerateException(String.format(DatabaseGenerateException.EXTERNAL_STORAGE_PERMISSION_DENIED, dbPath));
                }
                File path = new File(dbPath);
                if (!path.exists()) {
                    path.mkdirs();
                }
                dbName = dbPath + "/" + dbName;
            }
			mLitePalHelper = new LitePalOpenHelper(dbName, litePalAttr.getVersion());
		}
		return mLitePalHelper;
	}

可以很清楚的看到做了3件事:

(1)获取了LitePalAttr单例;

(2)根据xml中设置的Storage标签创建了保存数据库的文件夹;

(3)创建LitePalOpenHelper并返回。

逻辑比较清晰,(2)不用解释,(1)大致可以推测是解析了xml,将配置都存在了LitePalAttr中,先放过,我们先看(3),也就是LitePalOpenHelper:

@Override
	public void onCreate(SQLiteDatabase db) {
		Generator.create(db);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Generator.upgrade(db);
		SharedUtil.updateVersion(LitePalAttr.getInstance().getExtraKeyName(), newVersion);
	}

构造方法就是调用了父类的构造方法,主要看上面两个方法的实现,可以得知建表和更新表操作都在Generator中实现,并且DB的最新version是在SharedPreferences中存储的。

LitePal的模块化是比较规范的,接下来有两个方向可以走:

    1.去LitePalAttr看xml解析

    2.去Generator看建表和更新表的逻辑

先1后2,LitePalAttr:

	public static LitePalAttr getInstance() {
		if (litePalAttr == null) {
			synchronized (LitePalAttr.class) {
				if (litePalAttr == null) {
					litePalAttr = new LitePalAttr();
                    loadLitePalXMLConfiguration();
				}
			}
		}
		return litePalAttr;
	}

然后看loadLitePalXMLConfiguration()方法:

private static void loadLitePalXMLConfiguration() {
        if (BaseUtility.isLitePalXMLExists()) {
            LitePalConfig config = LitePalParser.parseLitePalConfiguration();
            litePalAttr.setDbName(config.getDbName());
            litePalAttr.setVersion(config.getVersion());
            litePalAttr.setClassNames(config.getClassNames());
            litePalAttr.setCases(config.getCases());
            litePalAttr.setStorage(config.getStorage());
        }
    }

关键在  LitePalConfig config = LitePalParser.parseLitePalConfiguration();  这一句,那我们先看一下LitePalConfig的结构:

/**
     * The version of database.
     */
    private int version;

    /**
     * The name of database.
     */
    private String dbName;

    /**
     * The case of table names and column names and SQL.
     */
    private String cases;

    /**
     * Define where the .db file should be. Option values: internal external.
     */
    private String storage;

    /**
     * All the model classes that want to map in the database. Each class should
     * be given the full name including package name.
     */
    private List<String> classNames;

我省略了其中自动生成的getter,setter方法,很显然这是一个单纯的bean,存储了数据库的基本信息。

那么接下来是LitePalParser.parseLitePalConfiguration():

public static LitePalConfig parseLitePalConfiguration() {
		if (parser == null) {
			parser = new LitePalParser();
		}
		return parser.usePullParse();
	}

到这里基本xml解析都做了什么就比较明确了,LitePalParser中只有3个方法,其中一个是读取assets文件夹的,另外两个分别是Pull解析和SAX解析,没有做什么特别的操作,那么解析xml的代码分析到这里就结束了,接下来回到回到Generator。

先码到这。

update 2018/6/12

Generator这一块在tablemanager包中,继承结构为:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值