Android,Parcelable如何serialized/deserialized,是否维护对象实例的引用?
Android, how is the Parcelable serialized/deserialized, does it maintain the reference to the object instance?
有一个片段,它希望通过片段的参数传入一个 IDataProvider
(可打包),并用它从存储库中获取数据。
这是 DataFragment
,它通过 bundle.getParcelable<Parcelable>(KEY_DATA_PROVIDER) as? IDataProvider
从参数中检索 dataProvider
class DataFragment: Fragment() {
interface IDataProvider : Parcelable {
fun getDataByUUID(uuid: String): IData?
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//retainInstance = true
var bundle = arguments
var dataProvider: IDataProvider = bundle.getParcelable<Parcelable>(KEY_DATA_PROVIDER) as? IDataProvider
// the provider is got from bundle.getParcelable
// and would expect the `IDataRepository` reference kept
// in the dataProvider should be lost in the
// serialize/deserialize of the Parcelable
// but it does not, and it is still working to be able to make the call and return the data from the repository
val data: Data = dataProvider?.getDataByUUID("xxx-yyy-zzz")
// the data is returned fine (???)
......
}
... ...
}
这是 activity,它将 IDataProvider
放入 DataFragment 实例的参数中
通过 Bundle().putParcelable(KEY_DATA_PROVIDER, dataProvider)
class DataActivity: Activity {
var dataProvider: DataProvider? = null
val viewModel = getViewModel() //get the viewModel which has the dataRepository
fun createFragment(): Fragment? {
dataProvider = DataProvider()
dataProvider?.let {
dataProvider.repository = viewModel?.getDataRepository()
val args = Bundle()
args.putParcelable(KEY_DATA_PROVIDER, dataProvider) //put the dataProvider in the Bundle with putParcelable
var dataFragment = DataFragment()
dataFragment.arguments = args // set to its arguments
return contentFragment
}
return null
}
override fun onDestroy() {
super.onDestroy()
dataProvider?.repository = null
}
// DataProvider implementation,
// it has a reference to a IDataRepository
// but is not serialized/deserialized when it is parceling
private var dataProvider: DataProvider? = null
class DataProvider() : DataFragment.IDataProvider {
var repository: IDataRepository? = null
override fun getDataByUUID(uuid: String): IData? {
return repository?.getData(uuid)
}
constructor(parcel: Parcel) : this() {}
override fun writeToParcel(parcel: Parcel, flags: Int) {}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<DataProvider> {
override fun createFromParcel(parcel: Parcel): DataProvider {
return ContentProvider(parcel)
}
override fun newArray(size: Int): Array<DataProvider?> {
return arrayOfNulls(size)
}
}
}
}
如果按照上面的实现方式,可以预期class DataProvider() : DataFragment.IDataProvider
中的成员变量repository
应该丢失,因为 writeToParcel()/readFromParcel().
中没有 serialized/deserialized 的代码
但是当 rrunning 它似乎在片段中从包中打包回来时,成员变量 repository
仍然有效。
任何人都知道为什么,或者 Parcelable 是如何serialized/deserialized?
看起来像是使用从 createFragment() 生成的片段
fun createFragment(): Fragment? {
dataProvider = DataProvider()
dataProvider?.let {
dataProvider.repository = viewModel?.getDataRepository()
val args = Bundle()
args.putParcelable(KEY_DATA_PROVIDER, dataProvider) //put the dataProvider in the Bundle with putParcelable
var dataFragment = DataFragment()
dataFragment.arguments = args // set to its arguments
return contentFragment
}
return null
}
并做
var bundle = createFragment().arguments
var dataProvider: IDataProvider = bundle.getParcelable<Parcelable>(KEY_DATA_PROVIDER) as? IDataProvider
该捆绑包仍然具有相同的包含 parcelables 实例,因此它仍然有效。
但是在像 os 这样的情况下,杀死并恢复片段,来自新片段 arguments
的 parcelable 将有新的 parcelable 实例,并且不再有以前的引用。
有一个片段,它希望通过片段的参数传入一个 IDataProvider
(可打包),并用它从存储库中获取数据。
这是 DataFragment
,它通过 bundle.getParcelable<Parcelable>(KEY_DATA_PROVIDER) as? IDataProvider
class DataFragment: Fragment() {
interface IDataProvider : Parcelable {
fun getDataByUUID(uuid: String): IData?
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//retainInstance = true
var bundle = arguments
var dataProvider: IDataProvider = bundle.getParcelable<Parcelable>(KEY_DATA_PROVIDER) as? IDataProvider
// the provider is got from bundle.getParcelable
// and would expect the `IDataRepository` reference kept
// in the dataProvider should be lost in the
// serialize/deserialize of the Parcelable
// but it does not, and it is still working to be able to make the call and return the data from the repository
val data: Data = dataProvider?.getDataByUUID("xxx-yyy-zzz")
// the data is returned fine (???)
......
}
... ...
}
这是 activity,它将 IDataProvider
放入 DataFragment 实例的参数中
通过 Bundle().putParcelable(KEY_DATA_PROVIDER, dataProvider)
class DataActivity: Activity {
var dataProvider: DataProvider? = null
val viewModel = getViewModel() //get the viewModel which has the dataRepository
fun createFragment(): Fragment? {
dataProvider = DataProvider()
dataProvider?.let {
dataProvider.repository = viewModel?.getDataRepository()
val args = Bundle()
args.putParcelable(KEY_DATA_PROVIDER, dataProvider) //put the dataProvider in the Bundle with putParcelable
var dataFragment = DataFragment()
dataFragment.arguments = args // set to its arguments
return contentFragment
}
return null
}
override fun onDestroy() {
super.onDestroy()
dataProvider?.repository = null
}
// DataProvider implementation,
// it has a reference to a IDataRepository
// but is not serialized/deserialized when it is parceling
private var dataProvider: DataProvider? = null
class DataProvider() : DataFragment.IDataProvider {
var repository: IDataRepository? = null
override fun getDataByUUID(uuid: String): IData? {
return repository?.getData(uuid)
}
constructor(parcel: Parcel) : this() {}
override fun writeToParcel(parcel: Parcel, flags: Int) {}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<DataProvider> {
override fun createFromParcel(parcel: Parcel): DataProvider {
return ContentProvider(parcel)
}
override fun newArray(size: Int): Array<DataProvider?> {
return arrayOfNulls(size)
}
}
}
}
如果按照上面的实现方式,可以预期class DataProvider() : DataFragment.IDataProvider
中的成员变量repository
应该丢失,因为 writeToParcel()/readFromParcel().
但是当 rrunning 它似乎在片段中从包中打包回来时,成员变量 repository
仍然有效。
任何人都知道为什么,或者 Parcelable 是如何serialized/deserialized?
看起来像是使用从 createFragment() 生成的片段
fun createFragment(): Fragment? {
dataProvider = DataProvider()
dataProvider?.let {
dataProvider.repository = viewModel?.getDataRepository()
val args = Bundle()
args.putParcelable(KEY_DATA_PROVIDER, dataProvider) //put the dataProvider in the Bundle with putParcelable
var dataFragment = DataFragment()
dataFragment.arguments = args // set to its arguments
return contentFragment
}
return null
}
并做
var bundle = createFragment().arguments
var dataProvider: IDataProvider = bundle.getParcelable<Parcelable>(KEY_DATA_PROVIDER) as? IDataProvider
该捆绑包仍然具有相同的包含 parcelables 实例,因此它仍然有效。
但是在像 os 这样的情况下,杀死并恢复片段,来自新片段 arguments
的 parcelable 将有新的 parcelable 实例,并且不再有以前的引用。