因为未知原因,突然想到了关于一个 List 集合里面能否添加不同对象的问题,因为我们平时开发过程中,关于List 的比较常规的写法就是:
List<XXX> list = new ArrayList<XXX>();
这让我形成了一种 List 里面就只能添加一种类型的对象的潜在想法(或许是 Java 基础不够扎实)。
所以,我这里用代码确定一下,List 不给定泛型,然后迭代添加两种不同的对象,最后再迭代输出数据,看看是否会有问题,代码如下:
public class MainClass { private List list = new ArrayList(); public static void main(String args[]) { MainClass mc = new MainClass(); mc.initData(); for (int i = 0; i < 10; i++) { Object item = mc.list.get(i); if (item instanceof TestOther) { TestOther other = (TestOther) item; String company = other.getCompany(); String position = other.getPosition(); System.out.println("company : " + company + " , position : " + position); } else if (item instanceof TestBean1) { String name = ((TestBean1) item).getName(); String like = ((TestBean1) item).getLike(); System.out.println("name : " + name + " , like : " + like); } } } private void initData() { for (int i = 0; i < 10; i++) { if (i % 2 == 0) { list.add(new TestOther("Ekoo" + i, "Android Developer" + i)); } else { list.add(new TestBean1("Test" + i, "Coding" + i)); } } } }
那么我们的运行结果如下:
company : Ekoo0 , position : Android Developer0 name : Test1 , like : Coding1 company : Ekoo2 , position : Android Developer2 name : Test3 , like : Coding3 company : Ekoo4 , position : Android Developer4 name : Test5 , like : Coding5 company : Ekoo6 , position : Android Developer6 name : Test7 , like : Coding7 company : Ekoo8 , position : Android Developer8 name : Test9 , like : Coding9
这里通过打印数据,确定了 List 中可以添加不同对象。
那么,这个问题明确之后,我想到了在之前的工作中,一直以为 ListView 列表数据中不能存有不同的对象,所有数据都只能在同一个对象中定义。这个时候,我们再去尝试一下,利用 List 中可以添加不同对象去测试一下 ListView 中 加载不同的布局。
首先,创建两个不同的对象 :
public class CompanyBean { private String company; private String position; private String address; public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public String getPosition() { return position; } public void setPosition(String position) { this.position = position; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } public class UserBean { private String name; private String age; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
然后,我们在 Activity 中初始化一下模拟数据:
private void initData() { for (int i = 0; i < 20; i++) { // 这里随机生成 1到10 之间的随机数 int num = (int) (Math.random() * 10); if (num % 2 == 0) { UserBean bean1 = new UserBean(); bean1.setName("name" + i); bean1.setAge(num + ""); bean1.setSex("男"); list.add(bean1); } else { CompanyBean bean2 = new CompanyBean(); bean2.setCompany("HzEkoo" + i); bean2.setAddress("Ypsd201-4(" + i + ")"); bean2.setPosition("Android Developer" + i); list.add(bean2); } } }
接下来就是定义 Adapter 了。
private class TestAdapter extends BaseAdapter { private Context context; private List list; private LayoutInflater inflater; public TestAdapter(Context context, List list) { this.context = context; this.list = list; inflater = LayoutInflater.from(context); } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { Object item = list.get(position); if (item instanceof UserBean) { return 0; } else if (item instanceof CompanyBean) { return 1; } return -1; } @Override public int getViewTypeCount() { return 2; } @Override public View getView(int position, View convertView, ViewGroup parent) { Object item = getItem(position); int type = getItemViewType(position); switch (type) { case 0: UserBean userBean = (UserBean) item; if (convertView == null) { convertView = inflater.inflate(R.layout.item_user, parent, false); } TextView tv_name = ViewHolder.get(convertView, R.id.tv_name); TextView tv_age = ViewHolder.get(convertView, R.id.tv_age); TextView tv_sex = ViewHolder.get(convertView, R.id.tv_sex); tv_name.setText(userBean.getName()); tv_age.setText(userBean.getAge()); tv_sex.setText(userBean.getSex()); break; case 1: CompanyBean comBean = (CompanyBean) item; if (convertView == null) { convertView = inflater.inflate(R.layout.item_company, parent, false); } TextView tv_company = ViewHolder.get(convertView, R.id.tv_company); TextView tv_position = ViewHolder.get(convertView, R.id.tv_position); tv_company.setText(comBean.getCompany()); tv_position.setText(comBean.getPosition()); break; } return convertView; } }
这个 Adapter 肯定是我最终的调试结果。关于 ViewHolder.get(View , id) 我之前博客 进一步简化你的 ViewHolder 有过介绍。
初期,我的想法是在 getView() 中根据判断 List 对应下标对象的类型 比如:
Object item = list.get(position); if (item instanceof UserBean) { UserBean userBean = (UserBean) item; // do something } else if (item instanceof CompanyBean) { CompanyBean comBean = (CompanyBean) item; // do something }
这样去判断加载不同的布局,进行数据填充,但是在进行滑动过程中,复用出现了混乱,导致直接闪退。
最终确定选择了使用 getItemViewType() 方法,不过,这个方法在使用的时候也是有个坑,那就是必须要重写getViewTypeCount() 方法,这个以前不怎么用,所以现在才发现这个问题。
最后附上一张效果图:
只是一个简单的测试,有需要源码的朋友,留个地址。
能力有限,欢迎各位指正。