赞
踩
当我编写quickupload库时,因为需要在 Service中进行上传任务,向Service传递时我发现需要传递的数据很多并且结构复杂,如果处理不好就会导致以下几个问题
为了解决这个问题,需要编写 PersistableData
open class PersistableData() : Parcelable { protected val data = HashMap<String, Any>() override fun equals(other: Any?): Boolean { if (other == null || other !is PersistableData) return false return data == other.data } override fun hashCode() = data.hashCode() @SuppressLint("ParcelClassLoader") private constructor(parcel: Parcel) : this() { parcel.readBundle()?.let { bundle -> bundle.keySet().forEach { key -> when (val value = bundle[key]) { is Boolean, is Double, is Int, is Long, is String -> data[key] = value } } } } override fun describeContents() = 0 override fun writeToParcel(dest: Parcel, flags: Int) { toBundle().writeToParcel(dest, flags) } companion object CREATOR : Parcelable.Creator<PersistableData> { private const val separator = "$" override fun createFromParcel(parcel: Parcel) = PersistableData(parcel) override fun newArray(size: Int): Array<PersistableData?> = arrayOfNulls(size) /** * 从PersistableData JSON表示创建 [PersistableData]。 */ @JvmStatic fun fromJson(rawJsonString: String): PersistableData { val json = JSONObject(rawJsonString) val data = PersistableData() json.keys().forEach { key -> when (val value = json.get(key)) { is Boolean, is Double, is Int, is Long, is String -> data.data[key] = value } } return data } } private fun String.validated(checkExists: Boolean = false): String { if (contains(separator)) throw IllegalArgumentException("key cannot contain $separator as it's a reserved character, used for nested data") if (checkExists && !data.containsKey(this)) throw IllegalArgumentException("no data found for key \"$this\"") return this } fun putBoolean(key: String, value: Boolean) { data[key.validated()] = value } fun getBoolean(key: String) = data[key.validated(checkExists = true)] as Boolean fun putDouble(key: String, value: Double) { data[key.validated()] = value } fun getDouble(key: String) = data[key.validated(checkExists = true)] as Double fun putInt(key: String, value: Int) { data[key.validated()] = value } fun getInt(key: String) = data[key.validated(checkExists = true)] as Int fun putLong(key: String, value: Long) { data[key.validated()] = value } fun getLong(key: String) = data[key.validated(checkExists = true)] as Long fun putString(key: String, value: String) { data[key.validated()] = value } fun getString(key: String) = data[key.validated(checkExists = true)] as String fun putData(key: String, data: PersistableData) { data.data.forEach { (dataKey, value) -> this.data["$key$separator$dataKey"] = value } } fun getData(key: String): PersistableData { val entries = data.entries.filter { it.key.startsWith("$key$separator") } if (entries.isEmpty()) return PersistableData() return PersistableData().also { extractedData -> entries.forEach { (entryKey, entryValue) -> extractedData.data[entryKey.removePrefix("$key$separator")] = entryValue } } } fun putArrayData(key: String, data: List<PersistableData>) { data.forEachIndexed { index, persistableData -> persistableData.data.forEach { (dataKey, value) -> this.data["$key$separator$index$separator$dataKey"] = value } } } fun getArrayData(key: String): List<PersistableData> { val entries = ArrayList(data.entries.filter { it.key.startsWith("$key$separator") }) if (entries.isEmpty()) return emptyList() var index = 0 var elements = entries.filter { it.key.startsWith("$key$separator$index$separator") } val outList = ArrayList<PersistableData>() while (elements.isNotEmpty()) { outList.add(PersistableData().also { extractedData -> elements.forEach { (entryKey, entryValue) -> extractedData.data[entryKey.removePrefix("$key$separator$index$separator")] = entryValue } entries.removeAll(elements) }) index += 1 elements = entries.filter { it.key.startsWith("$key$separator$index$separator") } } return outList } /** * 创建一个新的包,其中包含此 [PersistableData] 中存在的所有字段。 */ fun toBundle() = Bundle().also { bundle -> data.keys.forEach { key -> when (val value = data[key]) { is Boolean -> bundle.putBoolean(key, value) is Double -> bundle.putDouble(key, value) is Int -> bundle.putInt(key, value) is Long -> bundle.putLong(key, value) is String -> bundle.putString(key, value) } } } /** * 创建一个包含所有字段的JSON字符串表示 * 在此 [PersistableData] 中。 * * 这并不意味着人类可读,而是一种方便的方式来传递复杂的 * 使用字符串的结构化数据。 */ fun toJson() = JSONObject().also { json -> data.keys.forEach { key -> when (val value = data[key]) { is Boolean, is Double, is Int, is Long, is String -> json.put(key, value) } } }.toString() }
简单总结一下:
编写接口 Persistable
interface Persistable {
fun toPersistableData(): PersistableData
interface Creator<T> {
fun createFromPersistableData(data: PersistableData): T
}
}
简单总结一下:
当需要对某个数据类进行序列化时只需要实现接口 Persistable,例如 UploadFile数据类
@Parcelize data class UploadFile @JvmOverloads constructor( val path: String, val properties: LinkedHashMap<String, String> = LinkedHashMap() ) : Parcelable, Persistable { companion object : Persistable.Creator<UploadFile> { private object CodingKeys { const val path = "path" const val properties = "props" } override fun createFromPersistableData(data: PersistableData) = UploadFile( path = data.getString(CodingKeys.path), properties = LinkedHashMap<String, String>().apply { val bundle = data.getData(CodingKeys.properties).toBundle() bundle.keySet().forEach { propKey -> put(propKey, bundle.getString(propKey)!!) } } ) } override fun toPersistableData() = PersistableData().apply { putString(CodingKeys.path, path) putData(CodingKeys.properties, PersistableData().apply { properties.entries.forEach { (propKey, propVal) -> putString(propKey, propVal) } }) } }
简单总结一下:
我认为这样做 可以简化和优化在Android应用中管理复杂数据结构及其持久化的过程,如果对你有帮助记得点赞收藏!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。