android - 通用迁移
问题描述
我喜欢在 Android 应用程序中将各种东西从一个版本迁移到另一个版本。我的具体迁移都准备好了并且工作正常。我迁移 sharedPrefences,压缩图像多一点等等。
但我想不出处理:
- 每次迁移只优雅地运行一次。(到目前为止,它是用 shared.-pref MIGRATION_v1_DONE 完成的)。
- 不要为新安装运行迁移。
我在这里找到了这个项目。这很好,因为它只运行一次迁移,如果我退出异常,迁移将再次运行,因为它还没有完成。
但是这个项目也将为新安装运行迁移。所以我需要为每次迁移添加检查和更多检查。非常容易出错。我想使用该库但不用于新安装。
我在想类似的东西:
- 版本 1 到 2 的迁移类文件。
- 新安装已经是版本 2,不会被迁移。
- 将来版本 2 到 3 的类文件。
- 新安装已经是版本 3,不会迁移。
解决方案
引入一个 MigrationFactory 类,并且对于每个迁移,它都是从具有#migrate 功能的抽象类扩展而来的类。
整个迁移通过读取和写入BuildConfig.VERSION_CODE常量来进行。在第一次运行时(在引入 MigrationFactory 时进行新安装),此值为 0。循环从 0 迭代到当前 VERSION_CODE,并且当迭代与案例匹配时,切换案例开始运行。
在第一次运行 case 0 匹配。在我的构造中,这会检查 sharedPref 值是否存在。如果不是这种情况,应用程序是新安装的并且不需要迁移,int i 将设置为当前 VERSION_CODE,在 break 后切换 case,for 循环离开了我的 break。如果找到 sharedPref(应用程序已安装并且刚刚更新)循环连续 1、2、3... ohh 54 - 案例匹配并运行 V54Migration#migrate。
假设 BuildConfig.VERSION_CODE 当前为 72。 V72Migration 未运行。它将在 BuildConfig.VERSION_CODE = 73 上运行!在未来的某个版本中,可能需要在 VERSION_CODE = 77 上进行另一次迁移。这将在 VERSION_CODE 78 的版本上运行。
对于具有非常旧版本的应用程序(更新前的 VERSION_CODE = 10)并且现在应用程序是 VERSION_CODE 75 的人,将运行迁移 54、71 和 72。
public class MigrationFactory {
private static final String CURRENT_VERSIONCODE = "current_versioncode";
// ...
private void setVersionCode(int versionCode) {
PrefManager.with(mContext).save(CURRENT_VERSIONCODE, versionCode);
}
public boolean isMigrationNeeded() {
return getVersionCode() < BuildConfig.VERSION_CODE;
}
private int getVersionCode() {
//Empty during first run. Will return 0 instead.
return PrefManager.with(mContext).getInt(CURRENT_VERSIONCODE, 0);
}
public void createMigration() {
for (int i = getVersionCode(); i < BuildConfig.VERSION_CODE; i++) {
switch (i) {
case 0:
if (!mContext.getSharedPreferences(mContext.getPackageName())
.contains("a string only existent in an already installed version")})) {
Log.d(MainApplication.getTAG(this.getClass()), "I am a V0_NewInstall");
//if new install set i to current VERSION_CODE, no
//migrations needed in that case.
i = BuildConfig.VERSION_CODE;
//Now exist out the loop and switch case.
break;
}
break;
case 54:
new V54_CropJPGAvatarImages(mContext).migrate();
break;
case 71:
new V71_CompressJPG(mContext).migrate();
break;
case 72:
new V72_SetWhatever(mContext).migrate();
break;
case 77:
break;
}
}
setVersionCode(BuildConfig.VERSION_CODE);
}
}
我在我的 MainApplication#onCreate 中调用这个类:
MigrationFactory migrationFactory = MigrationFactory.getInstance(this);
if (migrationFactory.isMigrationNeeded())
migrationFactory.createMigration();
推荐阅读
- laravel - 为什么我不能在 Laravel 中创建 Mock
- sql - SQL计算一阶和二阶之间的平均时间?(根据 min 和 min+1 做 sql 计算?)
- python-3.x - 试图将许多 python 文件导入另一个
- php - 如何在 WooCommerce 中调整字段
- html - 如何以角度解析嵌套的json
- java - 客户端无法使用自签名证书连接到 REST API
- rust - 如何通过 curl 使用 actix-from-data 的映射数组发出 POST 请求?
- asp.net - 如何用我在 iis 服务器上运行的 asp.net 中的自定义值替换缓存控制安全标头值中的私有值
- jquery - jQuery - 有多个总计的总计
- sprite-kit - 如何使用 SpriteKit 在圆上通过给定偏移创建点?