Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/207.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如果已有房间数据库实例,如何填充该数据库?_Android_Kotlin_Android Room - Fatal编程技术网

Android 如果已有房间数据库实例,如何填充该数据库?

Android 如果已有房间数据库实例,如何填充该数据库?,android,kotlin,android-room,Android,Kotlin,Android Room,我希望我的用户能够将房间数据库保存在谷歌硬盘上,然后从另一台设备上加载,第一部分已经实现,但我正在努力用新文件填充房间数据库 这是我的数据库单例: companion object { @Volatile private var INSTANCE: AppRoomDataBase? = null fun getDatabase(context: Context): AppRoomDataBase { val tempInstance = INSTANCE

我希望我的用户能够将房间数据库保存在谷歌硬盘上,然后从另一台设备上加载,第一部分已经实现,但我正在努力用新文件填充房间数据库

这是我的数据库单例:

companion object {
    @Volatile
    private var INSTANCE: AppRoomDataBase? = null
    fun getDatabase(context: Context): AppRoomDataBase {
        val tempInstance = INSTANCE
        if (tempInstance != null) {
            return tempInstance
        }
        synchronized(this) {
            val instance = Room.databaseBuilder(
                context.applicationContext,
                AppRoomDataBase::class.java,
                "product_database"
            ).build()
            INSTANCE = instance
            return instance
        }
    }
}
然后,当用户希望从google drive加载数据库时:

 private fun loadFileFromDrive() {
    val file = File(getExternalFilesDir(null), "product_database")
    mDriveServiceHelper.queryFiles().addOnSuccessListener { fileList ->
       val database = fileList.files.first()
        mDriveServiceHelper.downloadFile(file,database.id)?.addOnSuccessListener {
                prepopulateRoomDatabaseWithFile(file)
        }
    }
}


private fun prepopulateRoomDatabaseWithFile(file : File){
    Room.databaseBuilder(application,AppRoomDataBase::class.java,"product_database")
        .createFromFile(file)
        .build()
}

但它不起作用,只有关于如何从文件中创建数据库的文档,但我找不到任何关于如何仅在需要时使用新的文件室数据库覆盖当前文件室数据库的内容,是否可能?

我认为您需要关闭原始数据库,然后构建第二个数据库设置实例

下面是一个示例(仅通过关闭然后重新打开单个数据库进行测试,请参见下面的示例)

  • 注意:为了方便和简洁,已使用allowMainThreadQueries
示例

下面的示例使用了上述方法(尽管是交换相同的数据库):-

运行时,日志包括:-

D/USERINFODB1: UserId = 0 UserName = UserFred
D/USERINFODB2: UserId = 0 UserName = UserFred

我尝试了MikeT解决方案,但它不起作用,因为我有许多不同的地方使用房间数据库,在每个地方我都必须传递一个信息,即应该使用新的数据库

对于我的案例,更好的解决方案是通过删除前一个数据库文件并将已加载的文件移动到旧数据库的目录中来切换数据库文件,如下所示:

private fun swapDatabaseFiles(file: File){
    AppRoomDataBase.getDatabase(applicationContext).close()
    databaseFile.delete()
    copyFile(file.absolutePath,databaseFile.name,databaseFile.absolutePath)
    prepopulateRoomDatabaseWithFile(file)  // TO OPEN DATABASE
    val mainActivity = Intent(applicationContext,MainActivity::class.java)  // NOW RESTARTING ACTIVITY SO DATABASE IS REFRESHED
    mainActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
    startActivity(mainActivity)
}



 private fun copyFile(inputPath: String, inputFileName: String, outputPath: String) {
    var inputStream: InputStream?
    var out: OutputStream?
    try {
        inputStream = FileInputStream(inputPath)
        out = FileOutputStream(outputPath + inputFileName)
        val buffer = ByteArray(1024)
        var read: Int
        while (inputStream.read(buffer).also { read = it } != -1) {
            out.write(buffer, 0, read)
        }
        inputStream.close()
        // write the output file (You have now copied the file)
        out.flush()
        out.close()
    } catch (fnfe1: FileNotFoundException) {
        fnfe1.message?.let { Log.e("tag fnfe1", it)
        }
    } catch (e: Exception) {
        Log.e("tag exception", e.message!!)
    }
}
在数据库的单例中交换数据库函数:

fun swapDatabase(context: Context,file : File){
            INSTANCE?.close()
            INSTANCE = null
            synchronized(this){
            val instance = Room.databaseBuilder(context.applicationContext,AppRoomDataBase::class.java,"product_database")
                .createFromFile(file)
                .build()
            INSTANCE = instance
        }
        }

编辑:重构代码并修复错误异常。现在一切正常。

您的解决方案是正确的,但在我的情况下不是这样,首先,如果您使用不同的数据库,您会发现它不工作,因为dao没有更新,其次,使用这种方法,我需要在我使用它的每个地方存储对新数据库的引用。
private fun swapDatabaseFiles(file: File){
    AppRoomDataBase.getDatabase(applicationContext).close()
    databaseFile.delete()
    copyFile(file.absolutePath,databaseFile.name,databaseFile.absolutePath)
    prepopulateRoomDatabaseWithFile(file)  // TO OPEN DATABASE
    val mainActivity = Intent(applicationContext,MainActivity::class.java)  // NOW RESTARTING ACTIVITY SO DATABASE IS REFRESHED
    mainActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
    startActivity(mainActivity)
}



 private fun copyFile(inputPath: String, inputFileName: String, outputPath: String) {
    var inputStream: InputStream?
    var out: OutputStream?
    try {
        inputStream = FileInputStream(inputPath)
        out = FileOutputStream(outputPath + inputFileName)
        val buffer = ByteArray(1024)
        var read: Int
        while (inputStream.read(buffer).also { read = it } != -1) {
            out.write(buffer, 0, read)
        }
        inputStream.close()
        // write the output file (You have now copied the file)
        out.flush()
        out.close()
    } catch (fnfe1: FileNotFoundException) {
        fnfe1.message?.let { Log.e("tag fnfe1", it)
        }
    } catch (e: Exception) {
        Log.e("tag exception", e.message!!)
    }
}
fun swapDatabase(context: Context,file : File){
            INSTANCE?.close()
            INSTANCE = null
            synchronized(this){
            val instance = Room.databaseBuilder(context.applicationContext,AppRoomDataBase::class.java,"product_database")
                .createFromFile(file)
                .build()
            INSTANCE = instance
        }
        }