У меня есть класс управления файлами, который может сохранить большой файл. Класс файлового менеджера является приложением-одиночкой, поэтому он переживает мои классы пользовательского интерфейса. Моя активность / фрагмент может вызывать save
функцию приостановки файлового менеджера из сопрограммы, а затем отображать успех или неудачу в пользовательском интерфейсе. Например:
//In MyActivity:
private fun saveTheFile() = lifecycleScope.launch {
try {
myFileManager.saveBigFile()
myTextView.text = "Successfully saved file"
} catch (e: IOException) {
myTextView.text = "Failed to save file"
}
}
//In MyFileManager
suspend fun saveBigFile() {
//Set up the parameters
//...
withContext(Dispatchers.IO) {
//Save the file
//...
}
}
Проблема этого подхода заключается в том, что я не хочу, чтобы операция сохранения была прервана, если действие завершено. Если действие будет уничтожено до начала работы блока withContext
или если в блоке withContext
есть какие-либо точки приостановки, сохранение не будет завершено, поскольку сопрограмма будет отменена.
Что я хочу случиться так, что файл всегда сохраняется. Если действие все еще существует, то мы можем показать обновления пользовательского интерфейса после его завершения.
Я подумал, что один из способов сделать это может состоять в том, чтобы запустить новый coroutineScope
из функции приостановки, подобной этой, но эта область видимости все еще кажется чтобы быть отмененным, когда отменяется его родительское задание.
suspend fun saveBigFile() = coroutineScope {
//...
}
Я думал, что другой альтернативой может быть сделать эту обычную функцию, которая обновляет некоторые LiveData, когда она закончена. Активность может наблюдать за живыми данными для результата, и, поскольку LiveData автоматически удаляет наблюдателей жизненного цикла, когда они уничтожаются, активность не передается в FileManager. Я хотел бы избежать этой схемы, если вместо этого можно сделать что-то менее запутанное, как указано выше.
//In MyActivity:
private fun saveTheFile() {
val result = myFileManager.saveBigFile()
result.observe(this@MyActivity) {
myTextView.text = when (it) {
true -> "Successfully saved file"
else -> "Failed to save file"
}
}
}
//In MyFileManager
fun saveBigFile(): LiveData<Boolean> {
//Set up the parameters
//...
val liveData = MutableLiveData<Boolean>()
MainScope().launch {
val success = withContext(Dispatchers.IO) {
//Save the file
//...
}
liveData.value = success
}
return liveData
}