为什么 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()
。
显然这并不适用于所有情况,所以我仍然想知道为什么会这样!
我正在使用一个名为 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()
。
显然这并不适用于所有情况,所以我仍然想知道为什么会这样!