为啥当 getParcelable 位于不同的 parceable 时会实例化不同的 parceable
Posted
技术标签:
【中文标题】为啥当 getParcelable 位于不同的 parceable 时会实例化不同的 parceable【英文标题】:why the different parceable get instantiated when getParcelable is on different one为什么当 getParcelable 位于不同的 parceable 时会实例化不同的 parceable 【发布时间】:2021-05-19 13:36:09 【问题描述】:在 android 中有一些可打包的类
@Parcelize
class ParcelableClassA(private val member: Int) : IAParcelable
init
Log.e("+++", "+++ ParcelableClassA::init, this: $this")
@Parcelize
class ParcelableClassB(private val member: String) : IBParcelable
init
Log.e("+++", "+++ ParcelableClassB::init, this: $this")
在某些地方它被实例化并放入一个包中以创建一个活动。
Intent(context, TheActivity::class.java).apply
val bundle = Bundle()
bundle.putParcelable(EXTRAS_CLASS_A, ParcelableClassA(1))
bundle.putParcelable(EXTRAS_CLASS_B, ParcelableClassB("B")
...
putExtras(bundle)
context.startActivity(this)
在活动类中:
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
val classA = intent.extras?.getParcelable(EXTRAS_CLASS_A) as? IAParcelable
val classB = intent.extras?.getParcelable(EXTRAS_CLASS_B) as? IBParcelable
预计只有一份打印输出"+++ ParcelableClassA::init, this: $this"
但实际上看到 ParcelableClassA 的两个实例被创建,一个在
intent.extras?.getParcelable(EXTRAS_CLASS_A)
和其他也发生的时候
intent.extras?.getParcelable(EXTRAS_CLASS_B)
被调用。所以 ParcelableClassA::init 和 ParcelableClassB::init 都被调用了两次。
如果额外放入的数据越多,调用的ParcelableClassA的实例化就越多,这只是浪费。
这是预期的行为还是这里的做法不正确?
更新: 似乎在 BaseBundle 中,如果在 unparcel() 中并且 mParcelledData 不为空,它将具有此行为。但不确定为什么会发生。 如果一步一步调试,mParcelledData 总是为空,没有这个问题,但是如果只是运行它就会显示这个问题。
void unparcel()
synchronized (this)
final Parcel source = mParcelledData;
if (source != null)
initializeFromParcelLocked(source, /*recycleParcel=*/ true, mParcelledByNative);
else
if (DEBUG)
Log.d(TAG, "unparcel "
+ Integer.toHexString(System.identityHashCode(this))
+ ": no parcelled data");
【问题讨论】:
【参考方案1】:看起来像是在使用intent.extra?导致问题。
如果更改为
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
var bundle = intent.extras
val classA = bundle?.getParcelable(EXTRAS_CLASS_A) as? IAParcelable
val classB = bundle?.getParcelable(EXTRAS_CLASS_B) as? IBParcelable
似乎没有看到副本。
【讨论】:
看起来像 Android 框架中的一个错误。您在哪个版本的 Android 上进行测试?您是否检查过运行不同 Android 版本的多台设备? 在 api 29 模拟器上运行。 kotlin intent.extras 可能会返回一个新的 Bundle(mExtras),同时使用bundle = intent.extras
,似乎 unparcel()
中的 initializeFromParcelLocked()
将清除 mParcelledData
,因此 dup 停止。不确定这是否属实,因为如果在调试中步骤它没有问题。/
通常Bundle
只拆包一次。这是一个惰性初始化,因此只要有对 Bundle
内容的引用就会发生。以上是关于为啥当 getParcelable 位于不同的 parceable 时会实例化不同的 parceable的主要内容,如果未能解决你的问题,请参考以下文章
当按钮位于 UITableViewCell 上时,为啥 UIButton showsTouchWhenHighlighted 不起作用?
当设备位于我的用户目录中时,为啥 Android 模拟器会报告“未知虚拟设备”?
bundle.getparcelable java.lang.classnotfoundexception怎么解决