Xamarin.Android: 之前插入到 ArrayAdapter 中的项目再次找不到
Xamarin.Android: item previously inserted in ArrayAdapter is not found again
我继承了这个 Xamarin.Android 应用程序,但它有一些问题。
一个特定的错误涉及 ArrayAdapter<ProductListObject>
,其中 ProductListObject
是子项目之间共享的常见 POCO(即 Android、Windows Phone 和 iOS);它只有几个属性(例如 Id
)并覆盖 (.NET) Equals()
方法以实现结构相等:
public class ProductListObject
{
public long Id { get; set; }
public override bool Equals(object obj)
{
if (!(obj is ProductListObject))
{
return false;
}
return Id == (obj as ProductListObject).Id;
}
}
问题是,每当我将此 ProductListObject
的实例放入 ArrayAdapter
中时,即使它们具有相同的 Id
,我也无法再次找到它:
var p1 = new ProductListObject { Id = 1 };
var p2 = new ProductListObject { Id = 1 };
var areEqual = p1.Equals(p2); // returns True, as expected
var productAdapter = new ArrayAdapter<ProductListObject>(this, 0, new[] { p1 });
var position = productAdapter.GetPosition(p2); // returns -1 >:(
我的问题是:我必须做什么才能让我的 POCO 在内部使用 Xamarin.Android 依赖于 Java equals()
方法的类型(like ArrayAdapter; which delegates to List.indexOf(Object) )?
我尝试过的:
- 已验证相应的 Java 版本是否按预期工作(确实如此)
- 覆盖
GetHashCode()
(没关系,如我所料)
- 在 Xamarin 文档中搜索并查看有关实施的信息
Equals()
(我没有发现特别相关的内容)
谢谢,
一月
当在 Android.Widget.ArrayAdapter
中使用时,.NET 对象似乎被包裹在 Java.Lang.Object
中。因此,在 productAdapter.GetPosition(...)
调用中使用的比较方法实际上是包装 Java.Lang.Object
.
的 java Equals(Java.Lang.Object o)
方法
要在两个对象具有相同的 Id
时使 ProductListObject
解析为相同的索引,请使 ProductListObject
派生自 Java.Lang.Object
,覆盖 Equals(Java.Lang.Object)
并将其转发给 .NET Equals(System.Object)
方法:
public class ProductListObject : Java.Lang.Object
{
public long Id { get; set; }
public override bool Equals(object obj) // Inherited from System.Object.
{
if (!(obj is ProductListObject))
{
return false;
}
return Id == (obj as ProductListObject).Id;
}
public override bool Equals (Java.Lang.Object o) // Inherited from Java.Lang.Object.
{
return this.Equals (o as System.Object);
}
}
如果您无法从 Java.Lang.Object
继承 ProductListObject
,另一种选择是实现您自己的代理 class:
public class ProductListObject
{
public long Id { get; set; }
public override bool Equals(System.Object obj)
{
if (!(obj is ProductListObject))
{
return false;
}
return Id == (obj as ProductListObject).Id;
}
}
public class JavaProxy: Java.Lang.Object
{
public Object Object { get; private set; }
public JavaProxy(System.Object o)
{
Object = o;
}
public override bool Equals (Java.Lang.Object o)
{
var proxy = o as JavaProxy;
if (o != null) {
return Object.Equals (proxy.Object);
}
return base.Equals (o);
}
}
// ...
var productAdapter = new ArrayAdapter<JavaProxy>(this, 0, new[] { new JavaProxy(p1) });
var position = productAdapter.GetPosition(new JavaProxy(p2));
它不像第一种方法那么干净,但它也有效。
我按照 Matt R 的建议做了,并创建了一个继承自 Java.Lang.Object
并委托给实际 .NET 对象的代理:
public class JavaObject<TValue> : Java.Lang.Object
{
public readonly TValue Value;
internal JavaObject(TValue value)
{
Value = value;
}
public override bool Equals(Java.Lang.Object that)
{
if (!(that is JavaObject<TValue>))
{
return false;
}
return Value.Equals((that as JavaObject<TValue>).Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
}
这不会将我与平台无关的 POCO 与 Android 实现联系起来,而且它不会强迫我锁定某些严格的继承树,这总是一个优点。
申请很简单:
var p1 = new JavaObject<ProductListObject>(new ProductListObject { Id = 1 });
var p2 = new JavaObject<ProductListObject>(new ProductListObject { Id = 1 });
var areEqual = p1.Equals(p2); // returns True, as expected
var productAdapter = new ArrayAdapter<JavaObject<ProductListObject>>(this, 0, new[] { p1 });
var position = productAdapter.GetPosition(p2); // returns 0!
我继承了这个 Xamarin.Android 应用程序,但它有一些问题。
一个特定的错误涉及 ArrayAdapter<ProductListObject>
,其中 ProductListObject
是子项目之间共享的常见 POCO(即 Android、Windows Phone 和 iOS);它只有几个属性(例如 Id
)并覆盖 (.NET) Equals()
方法以实现结构相等:
public class ProductListObject
{
public long Id { get; set; }
public override bool Equals(object obj)
{
if (!(obj is ProductListObject))
{
return false;
}
return Id == (obj as ProductListObject).Id;
}
}
问题是,每当我将此 ProductListObject
的实例放入 ArrayAdapter
中时,即使它们具有相同的 Id
,我也无法再次找到它:
var p1 = new ProductListObject { Id = 1 };
var p2 = new ProductListObject { Id = 1 };
var areEqual = p1.Equals(p2); // returns True, as expected
var productAdapter = new ArrayAdapter<ProductListObject>(this, 0, new[] { p1 });
var position = productAdapter.GetPosition(p2); // returns -1 >:(
我的问题是:我必须做什么才能让我的 POCO 在内部使用 Xamarin.Android 依赖于 Java equals()
方法的类型(like ArrayAdapter; which delegates to List.indexOf(Object) )?
我尝试过的:
- 已验证相应的 Java 版本是否按预期工作(确实如此)
- 覆盖
GetHashCode()
(没关系,如我所料) - 在 Xamarin 文档中搜索并查看有关实施的信息
Equals()
(我没有发现特别相关的内容)
谢谢, 一月
当在 Android.Widget.ArrayAdapter
中使用时,.NET 对象似乎被包裹在 Java.Lang.Object
中。因此,在 productAdapter.GetPosition(...)
调用中使用的比较方法实际上是包装 Java.Lang.Object
.
Equals(Java.Lang.Object o)
方法
要在两个对象具有相同的 Id
时使 ProductListObject
解析为相同的索引,请使 ProductListObject
派生自 Java.Lang.Object
,覆盖 Equals(Java.Lang.Object)
并将其转发给 .NET Equals(System.Object)
方法:
public class ProductListObject : Java.Lang.Object
{
public long Id { get; set; }
public override bool Equals(object obj) // Inherited from System.Object.
{
if (!(obj is ProductListObject))
{
return false;
}
return Id == (obj as ProductListObject).Id;
}
public override bool Equals (Java.Lang.Object o) // Inherited from Java.Lang.Object.
{
return this.Equals (o as System.Object);
}
}
如果您无法从 Java.Lang.Object
继承 ProductListObject
,另一种选择是实现您自己的代理 class:
public class ProductListObject
{
public long Id { get; set; }
public override bool Equals(System.Object obj)
{
if (!(obj is ProductListObject))
{
return false;
}
return Id == (obj as ProductListObject).Id;
}
}
public class JavaProxy: Java.Lang.Object
{
public Object Object { get; private set; }
public JavaProxy(System.Object o)
{
Object = o;
}
public override bool Equals (Java.Lang.Object o)
{
var proxy = o as JavaProxy;
if (o != null) {
return Object.Equals (proxy.Object);
}
return base.Equals (o);
}
}
// ...
var productAdapter = new ArrayAdapter<JavaProxy>(this, 0, new[] { new JavaProxy(p1) });
var position = productAdapter.GetPosition(new JavaProxy(p2));
它不像第一种方法那么干净,但它也有效。
我按照 Matt R 的建议做了,并创建了一个继承自 Java.Lang.Object
并委托给实际 .NET 对象的代理:
public class JavaObject<TValue> : Java.Lang.Object
{
public readonly TValue Value;
internal JavaObject(TValue value)
{
Value = value;
}
public override bool Equals(Java.Lang.Object that)
{
if (!(that is JavaObject<TValue>))
{
return false;
}
return Value.Equals((that as JavaObject<TValue>).Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
}
这不会将我与平台无关的 POCO 与 Android 实现联系起来,而且它不会强迫我锁定某些严格的继承树,这总是一个优点。
申请很简单:
var p1 = new JavaObject<ProductListObject>(new ProductListObject { Id = 1 });
var p2 = new JavaObject<ProductListObject>(new ProductListObject { Id = 1 });
var areEqual = p1.Equals(p2); // returns True, as expected
var productAdapter = new ArrayAdapter<JavaObject<ProductListObject>>(this, 0, new[] { p1 });
var position = productAdapter.GetPosition(p2); // returns 0!