Use streams to encode and decode the JSON backups
This significantly reduces memory usage. (We buffer the OutputStream because kotlinx.serialization flushes its internal buffers excessively[1]. We also buffer the InputStream for consistency, even though kotlinx.serialization uses adequate buffering; there is no performance impact because BufferedInputStream cascades harmlessly[2].) The functions encodeToStream() and decodeFromStream() are marked as experimental, but this is a pretty fundamental use case so surely it will continue to be supported in the future (maybe with minor changes). Fixes #6. [1] https://github.com/Kotlin/kotlinx.serialization/blob/v1.6.3/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt#L46 [2] https://github.com/openjdk/jdk/blob/jdk-23%2B14/src/java.base/share/classes/java/io/BufferedInputStream.java#L339
This commit is contained in:
parent
9534a1031a
commit
a7edeae6f3
2 changed files with 8 additions and 10 deletions
|
|
@ -7,8 +7,8 @@ import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.encodeToStream
|
||||||
import org.fossify.commons.activities.ManageBlockedNumbersActivity
|
import org.fossify.commons.activities.ManageBlockedNumbersActivity
|
||||||
import org.fossify.commons.dialogs.*
|
import org.fossify.commons.dialogs.*
|
||||||
import org.fossify.commons.extensions.*
|
import org.fossify.commons.extensions.*
|
||||||
|
|
@ -118,6 +118,7 @@ class SettingsActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
|
||||||
private fun exportMessages(uri: Uri) {
|
private fun exportMessages(uri: Uri) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
var success = false
|
var success = false
|
||||||
|
|
@ -128,11 +129,8 @@ class SettingsActivity : SimpleActivity() {
|
||||||
return@getMessagesToExport
|
return@getMessagesToExport
|
||||||
}
|
}
|
||||||
val json = Json { encodeDefaults = true }
|
val json = Json { encodeDefaults = true }
|
||||||
val jsonString = json.encodeToString(messagesToExport)
|
contentResolver.openOutputStream(uri)!!.buffered().use { outputStream ->
|
||||||
val outputStream = contentResolver.openOutputStream(uri)!!
|
json.encodeToStream(messagesToExport, outputStream)
|
||||||
|
|
||||||
outputStream.use {
|
|
||||||
it.write(jsonString.toByteArray())
|
|
||||||
}
|
}
|
||||||
success = true
|
success = true
|
||||||
toast(org.fossify.commons.R.string.exporting_successful)
|
toast(org.fossify.commons.R.string.exporting_successful)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.net.Uri
|
||||||
import android.util.Xml
|
import android.util.Xml
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
import org.fossify.commons.extensions.showErrorToast
|
import org.fossify.commons.extensions.showErrorToast
|
||||||
import org.fossify.commons.extensions.toast
|
import org.fossify.commons.extensions.toast
|
||||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||||
|
|
@ -37,13 +38,12 @@ class MessagesImporter(private val activity: SimpleActivity) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
|
||||||
private fun importJson(uri: Uri) {
|
private fun importJson(uri: Uri) {
|
||||||
try {
|
try {
|
||||||
val jsonString = activity.contentResolver.openInputStream(uri)!!.use { inputStream ->
|
val deserializedList = activity.contentResolver.openInputStream(uri)!!.buffered().use { inputStream ->
|
||||||
inputStream.bufferedReader().readText()
|
Json.decodeFromStream<List<MessagesBackup>>(inputStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
val deserializedList = Json.decodeFromString<List<MessagesBackup>>(jsonString)
|
|
||||||
if (deserializedList.isEmpty()) {
|
if (deserializedList.isEmpty()) {
|
||||||
activity.toast(org.fossify.commons.R.string.no_entries_for_importing)
|
activity.toast(org.fossify.commons.R.string.no_entries_for_importing)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue