Android,如何对Parcelable进行序列化/反序列化,它是否保持对对象实例的引用?

问题描述 投票:0回答:1

有一个片段,它期望IDataProvider(可以Parcelable)通过Fragment的参数传入,并与它一起从存储库中获取数据。

这是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 (???)
                    ......

        }

        ... ...
    }

这是活动,它通过IDataProviderBundle().putParcelable(KEY_DATA_PROVIDER, dataProvider)放入DataFragment实例的参数中

    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)
                }
            }
        }
    }

如果使用上面的实现,由于在writeToParcel()/ readFromParcel()中没有序列化/反序列化的代码,因此预期repository中的成员变量class DataProvider() : DataFragment.IDataProvider应该丢失。

但是当它运行时,当它从包中返回包裹时,成员变量repository仍然有效。

任何人都知道Parcelable被序列化/反序列化的原因或方式如何?

android parcelable
1个回答
0
投票

看起来如果使用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的新实例,并且将不再具有先前的引用。

© www.soinside.com 2019 - 2024. All rights reserved.