【问题标题】:Is it possible to compress a prepackaged database for room persistence library?是否可以为房间持久性库压缩预打包的数据库?
【发布时间】:2021-09-02 23:56:15
【问题描述】:

我有一个大约 150mb 的庞大数据库。我可以放置数据库的压缩版本吗?压缩到资产文件夹中以供房间使用还是不可能?

PS:android studio apk压缩不够

【问题讨论】:

  • 你可以,但你应该在提供文件到房间之前解压缩
  • 如何使用 Room?
  • 给我时间,我会展示
  • 非常感谢。
  • 还在等,先生。

标签: android database sqlite android-room


【解决方案1】:

首先,您需要一个可以将存档解压缩到某个目录的函数:

// unzip(new File("/sdcard/whatToUnzip.zip"), new File("/toThisFolder"));
fun unzip(zipFile: File, targetDirectory: File) {
    unzip(BufferedInputStream(FileInputStream(zipFile)), targetDirectory)
}

fun unzip(zipInputStream: InputStream, targetDirectory: File) {
    try {//BufferedInputStream(zipFileStream)
        ZipInputStream(zipInputStream).use { zipInput ->
            var zipEntry: ZipEntry
            var count: Int
            val buffer = ByteArray(65536)
            while (zipInput.nextEntry.also { zipEntry = it } != null) {
                val file = File(targetDirectory, zipEntry.name)
                val dir: File? = if (zipEntry.isDirectory) file else file.parentFile
                if (dir != null && !dir.isDirectory && !dir.mkdirs()) throw FileNotFoundException(
                    "Failed to ensure directory: " + dir.absolutePath
                )
                if (zipEntry.isDirectory) continue
                FileOutputStream(file).use { fileOutput ->
                    while (zipInput.read(buffer).also { count = it } != -1) fileOutput.write(
                        buffer,
                        0,
                        count
                    )
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

我从that stackoverflow's thread. 得到它,请阅读一个线程以获取更多详细信息。然后我添加了两种方法来处理应用程序资产文件夹中的文件:

fun unzipAsset(assetsFilePath: String, context: Context, targetDirectory: File) {
    unzip(context.assets.open(assetsFilePath), targetDirectory)
}

fun Context.unzipAsset(assetsFilePath: String, targetDirectory: File) = unzipAsset(
    assetsFilePath,
    this,
    targetDirectory
)

现在我们可以将文件解压缩到文件夹。为了避免在我使用createFromAssetRoom.databaseBuilder 的createFromFile 方法时按房间复制解压缩的数据库文件,我想将文件解压缩到应用程序databases 文件夹,该文件夹由房间用来存储数据库文件。这就是为什么我需要其他方法来获取 db 文件夹路径并检查 db 文件何时已存在:

fun Context.databaseFolderPath(): File? = this.getDatabasePath("any.db").parentFile

// name – The name of the database file.
fun Context.isRoomDbFileExist(name: String): Boolean  {
    return this.getDatabasePath(name)?.exists() ?: false
}

现在,如何一起使用所有的想法:

abstract class AppDatabase : RoomDatabase() {

companion object {

        private const val DB_NAME = "sunflower-db"

        // Create and pre-populate the database. See this article for more details:
        // https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1#4785
        private fun buildDatabase(context: Context): AppDatabase {
            if(!context.isRoomDbFileExist(DB_NAME)) {
                // unzip db file to app's databases directory to avoid copy of unzipped file by room
                context.unzipAsset("sunflower-db.zip", context.databaseFolderPath()!!)
                // or unzip(File("your file"), context.databaseFolderPath()!!)
            }
            return Room.databaseBuilder(context, AppDatabase::class.java, DB_NAME)
                //.createFromAsset(DB_NAME) // not zipped db file
                .build()
        }
    }
}

我在 nice open source project - sunflower 上测试了这段代码。接下来我想显示带有项目结构的屏幕,sunflower-db.zip 位于:

上述方法有效,但您不应将此示例视为正确或最佳解决方案。您应该考虑避免从主线程解压缩过程。如果您实现自己的SupportSQLiteOpenHelper.Factory(看起来很复杂),可能会更好。

【讨论】:

  • 正是我需要的。谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-01-19
  • 2018-05-27
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 2020-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多