【发布时间】:2019-04-19 20:12:10
【问题描述】:
在android应用程序中,有些情况需要传递一些数据,跨越activity/fragment,传递给服务等。它一直在使用parcelable并放入intent/bundle。它可以正常工作,只是有时会在超过 1 兆的 parcelable 限制时崩溃。
android.os.TransactionTooLargeException: data parcel size 526576 bytes
试图看看它是否可以将parcelable对象的内容放入lruCache,所以基本上用它自己的使用lruCache的实现来替换parcelable的保存/加载。
这种方法有什么问题吗?或者有什么建议/替代方案来解决这个问题?
@ApiSerializable
class DataItem (
@SerializedName("uuid")
var uuid: String = "",
@SerializedName("image")
val mainImage: Image?, //another parcelable type
@SerializedName("entities")
var entities: List<EntityInfo>?,
//......
// a lot of data
//......
//......
) : BaseDataItem(), IData {
override fun uuid(): String {
return uuid
}
//......
constructor(parcel: Parcel) : this(
parcel.readString(), //uuid
//...
//...
parcel.readParcelable(Image::class.java.classLoader),
mutableListOf<EntityInfo>().apply {
parcel.readTypedList(this, EntityInfo.CREATOR)
}) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(uuid ?: "")
//......
//......
parcel.writeParcelable(mainImage, flags)
parcel.writeTypedList(entities)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<DataItem> {
override fun createFromParcel(parcel: Parcel): DataItem {
return DataItem(parcel)
}
override fun newArray(size: Int): Array<DataItem?> {
return arrayOfNulls(size)
}
}
}
方法是使用 lruCache 本身替换包裹部分的保存/加载:
// having the cache somewhere
val dataCache = LruCache<String, IData>(200)
并且只有一个字符串成员与 Parcel 一起保存/加载:
fun init (copyData: DataItem) {
// do sopy over from the copyData
}
constructor(parcel: Parcel) : this() {
uuid = parcel.readString(), //uuid
val _thisCopy = dataCache.get(uuid)
init(_thisCopy)
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(uuid ?: "")
dataCache.put(uuid, this)
}
【问题讨论】:
-
简单。不要传递对象,而只是传递对象的标识符,然后在您想要对象的另一个屏幕中,从数据库中检索它
-
可能有一个数据列表在传递,如果对每一个项目都这样做,从数据库获取速度很慢。并且 DataItem 也可能是其他 parcelable 类的某个成员,不能简单地用“标识符”替换
-
你错了。数据库很快。获取列表很快。如果您的列表没有标识符,那么我强烈建议您更改应用程序的整个架构。如果您是 Android 新手,请开始阅读本文developer.android.com/jetpack/docs/guide
-
"并且 DataItem 也可能是其他可打包类的某个成员,不能简单地用“标识符”替换——嗯,它必须是,因为您需要一个标识符作为您的密钥
LruCache。使用缓存作为存储库的一部分是完全合理的,虽然偶尔会有点棘手。 -
感谢@CommonsWare,是的,“标识符”是 DataItem 中的“uuid”,只是另一个 Parceable 类可以将 DataItem 作为其成员,因此该类可以执行“包裹”操作并隐式地包裹 DataItem。听起来这种方法可行但“棘手”,有什么提示可能是需要注意的棘手部分吗?
标签: android parcelable android-lru-cache