Android数据库升级tips

唯一不变的是变化

App 版本迭代的过程中,一定会遇到sqlite 数据库需要升级的情况。一个简单粗暴的解决方法,是不顾用户的数据,直接去重建各个数据表。显然,今天要分享的并不是这个粗暴的方法。

常见的困惑

SQLiteOpenHelper提供了一个处理数据库升级的APIonUpgrade(final SQLiteDatabase db, int from, final int to)。从语义上来看,升级策略的描述应该有一个起始点from,也还应该有一个终点to。但由于起始点的不确定性,致使这里的代码分支会略显复杂。老实讲,在写这篇日志之前,我都没有把握温柔细致的处理好这件事。

灵感来源于android源码

DownloadManager也使用数据库存储下载状态。其子类DatabaseHelper将升级函数降维,把原本复杂的升级过程,分解为多个原子的升级过程,而这个原子过程是简单、确定的。直接上代码吧:

1
2
3
4
5
6
7
8
9
@Override
 public void onUpgrade(final SQLiteDatabase db, int oldV, final int newV) {
    ...
    //循环体内,每次只升一个版本
    for (int version = oldV + 1; version <= newV; version++) {
                upgradeTo(db, version);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Upgrade database from (version - 1) to version.
private void upgradeTo(SQLiteDatabase db, int version) {
    switch (version) {
        case 100:
            createDownloadsTable(db);
            break;
        case 101:
            createHeadersTable(db);
            break;
        case 102:
            addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_IS_PUBLIC_API,
                              "INTEGER NOT NULL DEFAULT 0");
            break;
        case 105:
            fillNullValues(db);
            break;
        ...
        default:
            throw new IllegalStateException("Don't know how to upgrade to " + version);
        }
}

以上代码不仅逻辑清晰,而且还能很好的复用。比如在onCreate函数里需要初始化数,就可以直接调用upgradeTo(db, CURRENT_VERSION).这样一来,无论是从哪个版本升级上来,都能平滑的处理版本问题了。

参考资料

Comments