[英]Android - Is using 'instanceof' the only way to determine the type of an item returned from a Spinner in “onItemSelected”?
As in the title - 如标题中所示-
Is there any way to determine the type of the item (typically either a String
, if adapted from a resource, or a generic Object
, if adapted programmatically) obtained from a Spinner in onItemSelected
? 是否有任何方法可以确定从
onItemSelected
的Spinner获得的项的类型(如果从资源改编,通常是String
,或者如果是通过编程改编,则是通用Object
)? In this case, I'm referring to one filled programmatically in Java, but as far as I know, it would be the same for one created from a String resource array. 在这种情况下,我指的是用Java以编程方式填充的代码,但据我所知,对于从String资源数组创建的代码来说,它是相同的。
Obviously, however, we create our Spinner, we know what type everything in it is. 但是,显然,我们创建了Spinner, 我们知道其中的所有内容都是什么类型。 If it's from resources, probably Strings.
如果来自资源,则可能是字符串。 If done programmatically, some kind of
Object
or possibly View
. 如果以编程方式完成,则使用某种
Object
或可能的View
。 However, the signature for onItemSelected
looks like this: 但是,
onItemSelected
的签名如下所示:
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// actions
// to get the item, you would usually do something like:
parent.getItemAtPosition(pos);
}
And obviously, the type we get from this is ?
显然,我们从中得到的类型是
?
, in other words, a generic Object
. ,换句话说就是通用
Object
。
So, if we know exactly what type it is, we can, of course, do this (example shown with an Integer
): 因此,如果我们确切知道它是什么类型,我们当然可以这样做(示例显示为
Integer
):
Object itemSelected = parent.getItemAtPosition(pos);
if (itemSelected instanceof Integer) doSomeMath((Integer) itemSelected);
But this doesn't exactly strike me as elegant. 但这并不完全使我感到优雅。 It works, certainly, at least in the simple cases I've given it (like
Integer
). 当然,它至少在我给出的简单情况下才有效(例如
Integer
)。 It might even be useful for handling multiple different types of Spinner
all running off the same listener
- I haven't actually tried that. 它甚至对于处理全部都在同一个
listener
Spinner
运行的多种不同类型的Spinner
可能很有用-我实际上没有尝试过。
But it seems like there should be a way to have the signature simply be something like: 但是似乎应该有一种方法可以使签名简单地像这样:
public void onItemSelected(AdapterView<Integer> parent, View view, int pos, long id)
Is using 'instanceof' the only way to determine the type of an item returned from a Spinner in “onItemSelected”?
使用“ instanceof”是确定“ onItemSelected”中从微调器返回的项目类型的唯一方法吗?
It is not the only way. 这不是唯一的方法。 But it it probably the best way.
但这可能是最好的方法。
Here are some alternatives: 以下是一些替代方案:
if (itemSelected.getClass().getName().equals("java.lang.Integer")) {
doSomeMath((Integer) itemSelected);
}
if (itemSelected.getClass() == Integer.class) {
doSomeMath((Integer) itemSelected);
}
try {
doSomeMath((Integer) itemSelected);
} catch (ClassCastException ex) {
// squash
}
Notes: 笔记:
instanceof
operator tests for subclasses as well, unlike the first two alternatives. instanceof
运算符也对子类进行测试。 ClassCastException
if it is thrown in the doSomeMath
method. doSomeMath
方法中抛出第三个版本,它将也挤压ClassCastException
。 null
. null
出现问题。 The instanceof
operator returns false for null
, but all of these alternatives will throw an NPE. instanceof
运算符为null
返回false,但是所有这些替代方案将抛出NPE。 Unfortunately, your alternative won't work. 不幸的是,您的替代方法无效。 The
AdapterView.OnItemSelectedListener
interface declares that method's first parameter with that type. AdapterView.OnItemSelectedListener
接口使用该类型声明该方法的第一个参数。 The interface is not generic. 该接口不是通用的。
But it seems like there should be a way to have the signature [...]
但似乎应该有一种方法来获得签名[...]
It seems but it can't be done because AdapterView.getItemAtPosition(int)
returns Object
anyway. 似乎但不能完成,因为
AdapterView.getItemAtPosition(int)
无论如何都会返回Object
。 ListView
or Spinner
don't know or care what type of items the adapter contains. ListView
或Spinner
不知道或不在乎适配器包含什么类型的项目。
Obviously, however, we create our Spinner, we know what type everything in it is.
但是,显然,我们创建了Spinner,我们知道其中的所有内容都是什么类型。
Exactly, since you're the ultimate master of what data you put in the adapter you should be able to cast it safely 确实,由于您是放入适配器的数据的最终掌握者,因此您应该能够安全地对其进行转换
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
final int item = (int) parent.getItemAtPosition(pos);
doSomeMath(item);
}
Instead of checking for an always true condition it would just crash when it encounters unexpected data. 它不会检查始终为真的条件,而只会在遇到意外数据时崩溃。
Get into this mindset: If something happens if it's not supposed to happen the code should throw an exception. 进入这种思维方式:如果某些事情如果不发生,那么代码应该抛出异常。 This gives you a chance to fix any errors instead of never knowing if there's anything wrong.
这使您有机会修复任何错误,而不用不知道是否有任何错误。
Another option would be having the adapter stored in a member variable and accessing it from the listener 另一个选择是将适配器存储在成员变量中,并从侦听器访问它
private MyAdapter adapter;
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
final int item = adapter.getItem(pos);
doSomeMath(item);
}
This assumes your adapter overrides getItem(int)
and returns the appropriate type. 假定您的适配器重写
getItem(int)
并返回适当的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.