为什么会TransactionTooLargeException
Activity/Fragment之间通过Bundle传递的参数过大导致,可能出现在启动界面或者界面开始保存数据onActivitySaveInstanceState/onFragmentSaveInstanceState中
如何判断Bundle的大小以及参数的大小
通过Parcel的dataSize方法即可获取对应Bundle的大小
/**
* Measure the size of a typed [Bundle] when written to a [Parcel].
*
* @param bundle to measure
* @return size when written to parcel in bytes
*/
fun sizeAsParcel(bundle: Bundle): Int {
val parcel = Parcel.obtain()
try {
parcel.writeBundle(bundle)
return parcel.dataSize()
} finally {
parcel.recycle()
}
}
/**
* Measure the size of a [Parcelable] when written to a [Parcel].
*
* @param parcelable to measure
* @return size of parcel in bytes
*/
fun sizeAsParcel(parcelable: Parcelable): Int {
val parcel = Parcel.obtain()
try {
parcel.writeParcelable(parcelable, 0)
return parcel.dataSize()
} finally {
parcel.recycle()
}
}
只需要获取参数大小,我们可以通过删除一个key然后计算一次大小,差值则为对应key的内存大小,当然,我们需要在计算完毕以后,把数据写回原来的Bundle
/**
* Measure the sizes of all the values in a typed [Bundle] when written to a
* [Parcel]. Returns a map from keys to the sizes, in bytes, of the associated values in
* the Bundle.
*
* @param bundle to measure
* @return a map from keys to value sizes in bytes
*/
fun sizeTreeFromBundle(bundle: Bundle): SizeTree {
val results = ArrayList<SizeTree>(bundle.size())
// We measure the totalSize of each value by measuring the total totalSize of the bundle before and
// after removing that value and calculating the difference. We make a copy of the original
// bundle so we can put all the original values back at the end. It's not possible to
// carry out the measurements on the copy because of the way Android parcelables work
// under the hood where certain objects are actually stored as references.
val copy = Bundle(bundle)
try {
var bundleSize = sizeAsParcel(bundle)
// Iterate over copy's keys because we're removing those of the original bundle
for (key in copy.keySet()) {
bundle.remove(key)
val newBundleSize = sizeAsParcel(bundle)
val valueSize = bundleSize - newBundleSize
results.add(SizeTree(key, valueSize, emptyList()))
bundleSize = newBundleSize
}
} finally {
// Put everything back into original bundle
bundle.putAll(copy)
}
return SizeTree("Bundle" + System.identityHashCode(bundle), sizeAsParcel(bundle), results)
}
如何自动判断
Activity可以通过Application.ActivityLifecycleCallbacks来监听,Fragment可以通过FragmentManager的registerFragmentLifecycleCallbacks来监听,详见https://27house.cn/archives/2356