Reputation: 11035
Having a fragment it expects an IDataProvider
(which is Parcelable) to be passed in through the Fragment's arguments, and with it to get the data from the repository.
this is the DataFragment
, which retrieves dataProvider from the arguments via 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 (???)
......
}
... ...
}
this is the activity, which puts an IDataProvider
in the arguments of the instance of the DataFragment
via 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)
}
}
}
}
If with the implementation above, it would be expected that the member variable repository
in the class DataProvider() : DataFragment.IDataProvider
should be lost since there is no code to serialized/deserialized in the writeToParcel()/readFromParcel().
But when rrunning it seems in the fragment when parcel it back from the bundle the member variable repository
is still valid.
Anyone knows why, or how the Parcelable is being serialized/deserialized?
Upvotes: 0
Views: 309
Reputation: 11035
looks like if using the generated fragment from 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
}
and do
var bundle = createFragment().arguments
var dataProvider: IDataProvider = bundle.getParcelable<Parcelable>(KEY_DATA_PROVIDER) as? IDataProvider
the bundle is still having the same instance of the contained parcelables, so it still works.
but in the case like os kill and restore the fragment, the parcelable from the new fragment's arguments
will have new instance of the parcelable, and that will not have the previous reference anymore.
Upvotes: 1