HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
来源:互联网 发布:mysql命令行界面建表 编辑:程序博客网 时间:2024/06/03 23:42
I was surprised that getViewTypeCount() is so rarely overrided (codesearch). If you are an expert in this – this post is not for you:-)
ListView and Adapter Basics
How it works:
- ListView asks adapter “give me a view” (getView) for each item of the list
- A new View is returned and displayed
Next question – what if we have one billion items? Create new view for each item? The answer is NO:-) Android caches views for you.
There’s a component in Android called “Recycler”. I drawed a picture based on Romain Guypresentation at Google IO ’09.
- If you have 1 billion items – there are only visible items in the memory + view in recycler.
- ListView asks for a view type1 first time (getView) x visible items. convertView is null in getView – you create new view of type1 and return it.
- ListView asks for a view type1 when one item1 is outside of the window and new item the same type is comming from the bottom. convertView is not null = item1. You should just set new data and return convertView back. No need to create view again.
Let’s write a simple code and put System.out to the getView:
public class MultipleItemsList extends ListActivity { private MyCustomAdapter mAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAdapter = new MyCustomAdapter(); for (int i = 0; i < 50; i++) { mAdapter.addItem("item " + i); } setListAdapter(mAdapter); } private class MyCustomAdapter extends BaseAdapter { private ArrayList mData = new ArrayList(); private LayoutInflater mInflater; public MyCustomAdapter() { mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void addItem(final String item) { mData.add(item); notifyDataSetChanged(); } @Override public int getCount() { return mData.size(); } @Override public String getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { System.out.println("getView " + position + " " + convertView); ViewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.item1, null); holder = new ViewHolder(); holder.textView = (TextView)convertView.findViewById(R.id.text); convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } holder.textView.setText(mData.get(position)); return convertView; } } public static class ViewHolder { public TextView textView; }}
getView was called 9 times. convertView is null for all visible items
02-05 13:47:32.559: INFO/System.out(947): getView 0 null02-05 13:47:32.570: INFO/System.out(947): getView 1 null02-05 13:47:32.589: INFO/System.out(947): getView 2 null02-05 13:47:32.599: INFO/System.out(947): getView 3 null02-05 13:47:32.619: INFO/System.out(947): getView 4 null02-05 13:47:32.629: INFO/System.out(947): getView 5 null02-05 13:47:32.708: INFO/System.out(947): getView 6 null02-05 13:47:32.719: INFO/System.out(947): getView 7 null02-05 13:47:32.729: INFO/System.out(947): getView 8 null
Then scroll the list slightly down (until item 10 appears):
convertView is still null because there is still no view in the recycler (border of item1 is still visible at the top:))
02-05 13:48:25.169: INFO/System.out(947): getView 9 null
Let’s scroll list a little more:
Bingo! convertView is not null: item1 goes off the screen directly to the Recycler and item11 is created based on item1.
02-05 13:48:42.879: INFO/System.out(947): getView 10 android.widget.LinearLayout@437430f8
scroll more just to check what hapens:
02-05 14:01:31.069: INFO/System.out(947): getView 11 android.widget.LinearLayout@437447d002-05 14:01:31.142: INFO/System.out(947): getView 12 android.widget.LinearLayout@43744ff802-05 14:01:31.279: INFO/System.out(947): getView 13 android.widget.LinearLayout@43743fa802-05 14:01:31.350: INFO/System.out(947): getView 14 android.widget.LinearLayout@4374582002-05 14:01:31.429: INFO/System.out(947): getView 15 android.widget.LinearLayout@4374604802-05 14:01:31.550: INFO/System.out(947): getView 16 android.widget.LinearLayout@4374687002-05 14:01:31.669: INFO/System.out(947): getView 17 android.widget.LinearLayout@4374709802-05 14:01:31.839: INFO/System.out(947): getView 18 android.widget.LinearLayout@437478c002-05 14:03:30.900: INFO/System.out(947): getView 19 android.widget.LinearLayout@43748df002-05 14:03:32.069: INFO/System.out(947): getView 20 android.widget.LinearLayout@437430f8
convertView is not null as we expected. After item11 goes off the screen, it view (@437430f8) comes as convertView for item 21. simple.
Different list items’ layouts
Let’s move to the “more complicated” example. How about to add separator somewhere to the list.
You should do the following:
- Override getViewTypeCount() – return how many different view layouts you have
- Override getItemViewType(int) – return correct view type id by position
- Create correct convertView (depending on view item type) in getView
Simple, isn’t it? Code snippet:
public class MultipleItemsList extends ListActivity { private MyCustomAdapter mAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAdapter = new MyCustomAdapter(); for (int i = 1; i < 50; i++) { mAdapter.addItem("item " + i); if (i % 4 == 0) { mAdapter.addSeparatorItem("separator " + i); } } setListAdapter(mAdapter); } private class MyCustomAdapter extends BaseAdapter { private static final int TYPE_ITEM = 0; private static final int TYPE_SEPARATOR = 1; private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1; private ArrayList mData = new ArrayList(); private LayoutInflater mInflater; private TreeSet mSeparatorsSet = new TreeSet(); public MyCustomAdapter() { mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void addItem(final String item) { mData.add(item); notifyDataSetChanged(); } public void addSeparatorItem(final String item) { mData.add(item); // save separator position mSeparatorsSet.add(mData.size() - 1); notifyDataSetChanged(); } @Override public int getItemViewType(int position) { return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM; } @Override public int getViewTypeCount() { return TYPE_MAX_COUNT; } @Override public int getCount() { return mData.size(); } @Override public String getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; int type = getItemViewType(position); System.out.println("getView " + position + " " + convertView + " type = " + type); if (convertView == null) { holder = new ViewHolder(); switch (type) { case TYPE_ITEM: convertView = mInflater.inflate(R.layout.item1, null); holder.textView = (TextView)convertView.findViewById(R.id.text); break; case TYPE_SEPARATOR: convertView = mInflater.inflate(R.layout.item2, null); holder.textView = (TextView)convertView.findViewById(R.id.textSeparator); break; } convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } holder.textView.setText(mData.get(position)); return convertView; } } public static class ViewHolder { public TextView textView; }}
Let’s run what we wrote. Yo will see separators after each 4-th item in the list.
In the log – nothing exceptional – all convertView is null for visible items both types.
02-05 15:19:03.080: INFO/System.out(1035): getView 0 null type = 002-05 15:19:03.112: INFO/System.out(1035): getView 1 null type = 002-05 15:19:03.130: INFO/System.out(1035): getView 2 null type = 002-05 15:19:03.141: INFO/System.out(1035): getView 3 null type = 002-05 15:19:03.160: INFO/System.out(1035): getView 4 null type = 102-05 15:19:03.170: INFO/System.out(1035): getView 5 null type = 002-05 15:19:03.180: INFO/System.out(1035): getView 6 null type = 002-05 15:19:03.190: INFO/System.out(1035): getView 7 null type = 002-05 15:19:03.210: INFO/System.out(1035): getView 8 null type = 002-05 15:19:03.210: INFO/System.out(1035): getView 9 null type = 1
Scroll list and see what happens:
02-05 15:19:54.160: INFO/System.out(1035): getView 10 null type = 002-05 15:19:57.440: INFO/System.out(1035): getView 11 android.widget.LinearLayout@43744528 type = 002-05 15:20:01.310: INFO/System.out(1035): getView 12 android.widget.LinearLayout@43744eb0 type = 002-05 15:20:01.880: INFO/System.out(1035): getView 13 android.widget.LinearLayout@437456d8 type = 002-05 15:20:02.869: INFO/System.out(1035): getView 14 null type = 102-05 15:20:06.489: INFO/System.out(1035): getView 15 android.widget.LinearLayout@43745f00 type = 002-05 15:20:07.749: INFO/System.out(1035): getView 16 android.widget.LinearLayout@43747170 type = 002-05 15:20:10.250: INFO/System.out(1035): getView 17 android.widget.LinearLayout@43747998 type = 002-05 15:20:11.661: INFO/System.out(1035): getView 18 android.widget.LinearLayout@437481c0 type = 002-05 15:20:13.180: INFO/System.out(1035): getView 19 android.widget.LinearLayout@437468a0 type = 102-05 15:20:16.900: INFO/System.out(1035): getView 20 android.widget.LinearLayout@437489e8 type = 002-05 15:20:25.690: INFO/System.out(1035): getView 21 android.widget.LinearLayout@4374a8d8 type = 0
convertView is null for separator view type until first separator is visible. When it goes off the screen – view also comes to the Recycler and convertView comes to play.
MultipleItemsList.zip – source code
备用下载地址:http://pan.baidu.com/share/link?shareid=304874&uk=2399475569
原文:http://android.amberfog.com/?p=296
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- Moving items up and down in a ListView control
- Drag and Drop Items in a WPF ListView
- ListView adapter getView 报错: addView(View, LayoutParams) is not supported in AdapterView
- ListView的adapter中getView被多次调用的问题
- android listView 重写Adapter方法getView的性能优化问题
- Android ListView 第一次设置Adapter时候getView调用多次
- ListView,GridView的Adapter中的getView执行异常
- adapter的 getView 获取ListView的Position位置的ItemView
- ListView,GridView,Gallery的Adapter中的getView多次调
- android使用ListView和Adapter.getView Recycler的工作原理
- android使用ListView和Adapter.getView Recycler的工作原理
- Hoj 2278 IP Filtering
- JS的传递数据不刷新页面的应用
- Android 中未公开的类(用@hide隐藏的类)
- Android读写文件总结
- MFC 获取临时目录 && 动态修改菜单栏
- HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
- Ajax技术原理解析
- redis sds.h文件分析
- C++ 控制小数位
- C#生成word时发生“外部组件发生异常”
- 10个经典的面向对象设计原则
- 两大Web图表工具PK:JreeChart和ChartDirector
- (读后感)C++ Primer(第四版) 第二章 变量和基本类型
- Havel定理---Frogs' Neighborhood