为什么 Parcel.ReadStringList() 在 MonoDroid 中写一个空列表?

Why is Parcel.ReadStringList() writing an empty list in MonoDroid?

我正在使用一个名为 GameSettings 的自定义 parcelable 对象在 Android 应用程序(使用 MonoDroid 开发)中的 Activite 之间传递一些设置。这些设置作为属性存储在此 GameSettings class 上,直到现在它们都是简单的整数,我已经能够使用 Parcel.WriteInt() 和 [=18 很好地打包它们=].

我刚刚向 GameSettings 添加了一个名为 CelebrityNames 的新 属性,它的类型为 List<string>,我正试图将其传递给相同的对象方式,但是当调用 ReadStringList() 时,属性 会填充一个空列表(尽管在此之前使用 WriteStringList() 将非空列表写入包裹)。包裹正在从 NameEntryActivity 传递到 GameRoundActivity

GameSettings.cs

using System;
using System.Collections.Generic;
using Android.OS;
using Java.Interop;
using Object = Java.Lang.Object;

namespace Celebrities
{
    public class GameSettings : Object, IParcelable
    {
        private static readonly GenericParcelableCreator<GameSettings> _creator 
            = new GenericParcelableCreator<GameSettings>((parcel) => new GameSettings(parcel));

        [ExportField("CREATOR")]
        public static GenericParcelableCreator<GameSettings> InitializeCreator() 
        {
            return _creator;
        }

        public int NumberOfPlayers { get; set; }
        public int NumberOfTeams { get; set; }
        public int CelebritiesPerPlayer { get; set; }
        public int SecondsPerRound { get; set; }

        private List<string> _celebrityNames;
        public List<string> CelebrityNames { 
            get 
            {
                _celebrityNames.Shuffle ();
                return _celebrityNames;
            } 
            set 
            { 
                _celebrityNames = value;
            } 
        }

        public GameSettings (int players, int teams, int celebrities, int secondsPerRound)
        {
            NumberOfPlayers = players;
            NumberOfTeams = teams;
            CelebritiesPerPlayer = celebrities;
            SecondsPerRound = secondsPerRound;
        }

        private GameSettings(Parcel parcel) : this(parcel.ReadInt (), parcel.ReadInt (), parcel.ReadInt (), parcel.ReadInt ())
        {
            if (_celebrityNames == null)
            {
                _celebrityNames = new List<string>();
            }
            parcel.ReadStringList (_celebrityNames);
        }

        public void WriteToParcel(Parcel dest, ParcelableWriteFlags flags) 
        {
            dest.WriteInt (NumberOfPlayers);
            dest.WriteInt (NumberOfTeams);
            dest.WriteInt (CelebritiesPerPlayer);
            dest.WriteInt (SecondsPerRound);
            dest.WriteStringList (_celebrityNames);
        }

        public int DescribeContents() 
        {
            return 0;
        }
    }
}

注意:我正在使用支持变量 _celebrityNames 进行打包,因为我有一个自定义的 getter 可以随机排列列表,此时不需要这样做。无论使用 属性 还是变量,问题都是一样的。

GenericParcelableCreator.cs

using System;
using Android.OS;
using Object = Java.Lang.Object;

namespace Celebrities
{
    public sealed class GenericParcelableCreator<T> : Object, IParcelableCreator
        where T : Object, new()
    {
        private readonly Func<Parcel, T> _createFunc;

        public GenericParcelableCreator(Func<Parcel, T> createFromParcelFunc)
        {
            _createFunc = createFromParcelFunc;
        }

        public Object CreateFromParcel(Parcel source)
        {
            return _createFunc(source);
        }

        public Object[] NewArray(int size)
        {
            return new T[size];
        }
    }
}

我在下面包含了 Activity classes 中的相关代码(为简洁起见,这些不是完整的文件,请询问您是否认为查看其余部分也会有所帮助).

NameEntryActivity.cs(我从哪里传递包裹)

public class NameEntryActivity : Activity
{
    ...    

    private GameSettings _gameSettings;
    private List<string> _celebrityNames;

    protected override void OnCreate (Bundle savedInstanceState)
    {
        ...

        _gameSettings = (Intent.Extras.GetParcelable ("GameSettings") as GameSettings);
        _celebrityNames = new List<string> ();

        ...
    }

    ...

    private void MoveToNextCelebrity() 
    {
        ...

        _gameSettings.CelebrityNames = _celebrityNames;

        var intent = new Intent (this, typeof(GameRoundActivity));
        intent.PutExtra("GameSettings", _gameSettings);
        StartActivity (intent);

        ...
    }
}

GameRoundActivity.cs(我把包裹寄到的地方)

public class GameRoundActivity : Activity
{
    private GameSettings _gameSettings;

    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);

        SetContentView (Resource.Layout.GameRound);

        _gameSettings = (Intent.Extras.GetParcelable ("GameSettings") as GameSettings);
    }
}

这是我第一次开发 Android 应用程序,所以很可能是我在实施 parcelling 框架的某个地方犯了错误或者误解了它。同样,我已经查看这段代码很长时间了,也许我只是遗漏了一个更普遍的愚蠢错误 :)

提前致谢!

我改用字符串数组而不是列表,现在可以使用 Parcel.WriteStringArray()Parcel.CreateStringArray()

显然这并不适用于所有情况,所以我仍然想知道为什么会这样!