2

我有一个多态实体列表,例如List<Person>一个人可以是员工、经理、士兵、皇室成员等......我想在一个 android 列表视图中显示人员列表,其中每种类型的人都有不同的行模板和有些不同的数据。

显示不同类型的不同行的正确方法是什么?

两个不好的(?)解决方案:

  1. 在类中放置一个抽象getView方法Person,以便每个不同的人通过多态创建正确的视图。--> 这将混合模型和 MVC 的视图 - 即。如果我想在不同的屏幕(例如表格视图)中显示列表,那么它将中断。

  2. 将模型到视图的逻辑放在适配器中(继承自ArrayAdapter<Person>)。例如在里面getView我可以检查这个getClass()人并相应地填充正确的视图。--> 这个方法最终会得到一长串 if-else 语句,每个人类型一个,并且在添加新类型的人时需要扩展——从面向对象的角度来看,这通常是一种糟糕的代码气味。这是“如何创建具有不同元素和动作的列表? ”中建议的解决方案。

有比上述(2)更好的解决方案吗?

4

3 回答 3

2

我个人会寻求类似于您的第二个解决方案的东西。我可能会在Person类中包含一个抽象方法来识别人员的类型,因此您可以使用它而不是检查调用中getClass()Person对象getView()

在您的自定义适配器中,扩展BaseAdapter并确保getViewTypeCount()返回您在数据集中拥有的不同类型的人的数量,并getItemViewType(int position)返回数据集中位置的正确标识符。

这个问题有很多关于这个主题的有用信息:

ArrayAdapter 的 getViewTypeCount 和 getItemViewType 方法

于 2013-06-17T16:31:32.697 回答
1

您可以在适配器中覆盖两种方法,使这更容易。他们是:

@Override
public int getViewTypeCount(){
  return viewTypeCount;
}

@Override
public int getItemViewType(int pos){
  if (getItem(pos).type == employee)
    return VIEW_TYPE_EMPLOYEE;
  else if (getItem(pos).type == manager)
    return VIEW_TYPE_MANAGER;
}

使用上述方法,你仍然需要做一些工作,例如当视图需要膨胀时,你可能必须从 getView 内部调用 getItemViewType(position),但是当你得到一个已经被回收的视图时,适配器应该给出您根据行位置选择正确的类型。

于 2013-06-17T16:40:52.523 回答
1

创建您自己的 ListAdapter,它像这样从 BaseAdapter 扩展

public class YourListAdapter extends BaseAdapter implements Filterable {
...
}

覆盖 getViewTypeCount() 和 getItemViewType()

@Override
public int getViewTypeCount() {
    return 2;//count of types
}

@Override
public int getItemViewType(int position) {
    return YourPersonList.get(position).getMyViewType();
}

并在 getView(..)

int type = getItemViewType(position);
switch(type){
case 0:
 //set the view to your layout
break;
case 1:
 //set the view to another layout
break;
}

或多或少是这样的..

//编辑:查看来自 michel https://stackoverflow.com/a/17152430/1847899的帖子

于 2013-06-17T16:33:56.957 回答