首页 > 代码库 > android ListView 分析(一)
android ListView 分析(一)
需要了解的内容
1. listview中的getItemAtPosition与Adapter的getItem的position的区别
listView中的getItemAtPosition的源码实现:
1 /** 2 * Gets the data associated with the specified position in the list. 3 * 4 * @param position Which data to get 5 * @return The data associated with the specified position in the list 6 */ 7 public Object getItemAtPosition(int position) { 8 T adapter = getAdapter(); 9 return (adapter == null || position < 0) ? null : adapter.getItem(position);10 }11 12 public long getItemIdAtPosition(int position) {13 T adapter = getAdapter();14 return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position);15 }
如果在adapter部位null并且position不是负数的时候,那么就会直接调用listView中真正的adapter的getItem()方法
因而我们自己定义的adapter,其实和listView中定义的getItemAtPosition()存在的差异就是在有headView和footView的时候
但是在我们自己的adapter中还是应该用有效的position
而在外部想直接调用的时候,应该让listView.getAdapter().getItem(position),如果调用到了headView或者footView的时候,那么就是返回为空的,因为在包装的
那么就是调用的headViewInfo中的data或者mFooterViewInfos.data
1 public Object getItem(int position) { 2 // Header (negative positions will throw an ArrayIndexOutOfBoundsException) 3 int numHeaders = getHeadersCount(); 4 if (position < numHeaders) { 5 return mHeaderViewInfos.get(position).data; 6 } 7 8 // Adapter 9 final int adjPosition = position - numHeaders;10 int adapterCount = 0;11 if (mAdapter != null) {12 adapterCount = mAdapter.getCount();13 if (adjPosition < adapterCount) {14 return mAdapter.getItem(adjPosition);15 }16 }17 18 // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)19 return mFooterViewInfos.get(adjPosition - adapterCount).data;20 }21 这个算是简单的View的包装器22 /**23 * A class that represents a fixed view in a list, for example a header at the top24 * or a footer at the bottom.25 */26 public class FixedViewInfo {27 /** The view to add to the list */28 public View view;29 /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */30 public Object data;31 /** <code>true</code> if the fixed view should be selectable in the list */32 public boolean isSelectable;33 }
2. listview中如何传递position
在listView中获得的position是经过包装的,因而在我们的adapter中需要转换
3. onItemClick的parent是否与listview为同一个view --> 是的
4. 在获取类型时,到底应该使用那个类型
在使用类型的时候,即getViewTypeCount()一般都是我们的adapter的getViewTypeCount()
5.adapter中 getItemViewType()方法的作用
我们使用的都是正数,而且是从0开始的,但是系统中的headView和footView的ViewType是负数
6.listView的优化
7.listView的扩展
7.1 listView实现下拉刷新,下拉加载
7.2 listView实现其他特效
7.3 listView实现动态的更改headView和footView的大小
......
8.listView相关知识: adapter的体系结构以及特点
ListView 在 存在headView或者footView的时候,listView设置的adapter并不是我们设置的adapter
查看源码便得知
1 /** 2 * Sets the data behind this ListView. 3 * 4 * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter}, 5 * depending on the ListView features currently in use. For instance, adding 6 * headers and/or footers will cause the adapter to be wrapped. 7 * 8 * @param adapter The ListAdapter which is responsible for maintaining the 9 * data backing this list and for producing a view to represent an10 * item in that data set.11 *12 * @see #getAdapter()13 */14 @Override15 public void setAdapter(ListAdapter adapter) {16 if (null != mAdapter) {17 mAdapter.unregisterDataSetObserver(mDataSetObserver);18 }19 20 resetList();21 mRecycler.clear();22 //关键代码 ListView 在 存在headView或者footView的时候,listView设置的adapter并不是我们设置的adapter,而是包装过的HeaderViewListAdapter23 24 25 if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {26 mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);27 } else {28 mAdapter = adapter;29 }30 31 ......32 }
既然如此设计,那么在使用的时候,我们便需要注意一些细节
listView中获取的getItemAtPosition中的position并不一定和我们的adapter的position相同
因而在设置position的时候,需要将position进行处理
例如
onItemClick中,传递而来的position有可能是包裹后的,因而我们考虑手工去除或者让系统来去除,即将包裹后的position转换为我们的adapter的position
1.手工方式
1 listView.setOnItemClickListener(new OnItemClickListener() {2 3 @Override4 public void onItemClick(AdapterView<?> parent, View view,5 int position, long id) {6 int realPosition = position - listView.getHeaderViewsCount();7 }8 });
2. 调用系统api的方式(推荐使用的方式)
在设置listView的相关监听的时候,会提供AdapterView<?> parent这个参数,这个其实就是我们的listView
调用他的getAdapter()获取到实际的adapter,然后调用adapter的获取数据的方式
1 @Override2 public void onItemClick(AdapterView<?> parent, View v, int position, long id) {3 doSomething(parent.getAdapter().getItem(position));4 }
1 2 扩展内容,包裹的adapter --> HeaderViewListAdapter 3 4 ...... 5 import java.util.ArrayList; 6 7 /** 8 * ListAdapter used when a ListView has header views. This ListAdapter 9 * wraps another one and also keeps track of the header views and their 10 * associated data objects. 11 *<p>This is intended as a base class; you will probably not need to 12 * use this class directly in your own code. 13 */ 14 public class HeaderViewListAdapter implements WrapperListAdapter, Filterable { 15 16 private final ListAdapter mAdapter; 17 18 // These two ArrayList are assumed to NOT be null. 19 // They are indeed created when declared in ListView and then shared. 20 ArrayList<ListView.FixedViewInfo> mHeaderViewInfos; 21 ArrayList<ListView.FixedViewInfo> mFooterViewInfos; 22 23 // Used as a placeholder in case the provided info views are indeed null. 24 // Currently only used by some CTS tests, which may be removed. 25 static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST = 26 new ArrayList<ListView.FixedViewInfo>(); 27 ...... 28 29 public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos, 30 ArrayList<ListView.FixedViewInfo> footerViewInfos, 31 ListAdapter adapter) { 32 mAdapter = adapter; 33 mIsFilterable = adapter instanceof Filterable; 34 35 if (headerViewInfos == null) { 36 mHeaderViewInfos = EMPTY_INFO_LIST; 37 } else { 38 mHeaderViewInfos = headerViewInfos; 39 } 40 41 if (footerViewInfos == null) { 42 mFooterViewInfos = EMPTY_INFO_LIST; 43 } else { 44 mFooterViewInfos = footerViewInfos; 45 } 46 47 mAreAllFixedViewsSelectable = 48 areAllListInfosSelectable(mHeaderViewInfos) 49 && areAllListInfosSelectable(mFooterViewInfos); 50 } 51 52 public int getHeadersCount() { 53 return mHeaderViewInfos.size(); 54 } 55 56 public int getFootersCount() { 57 return mFooterViewInfos.size(); 58 } 59 60 public boolean isEmpty() { 61 return mAdapter == null || mAdapter.isEmpty(); 62 } 63 64 ...... 65 66 public boolean removeHeader(View v) { 67 for (int i = 0; i < mHeaderViewInfos.size(); i++) { 68 ListView.FixedViewInfo info = mHeaderViewInfos.get(i); 69 if (info.view == v) { 70 mHeaderViewInfos.remove(i); 71 72 mAreAllFixedViewsSelectable = 73 areAllListInfosSelectable(mHeaderViewInfos) 74 && areAllListInfosSelectable(mFooterViewInfos); 75 76 return true; 77 } 78 } 79 80 return false; 81 } 82 83 public boolean removeFooter(View v) { 84 for (int i = 0; i < mFooterViewInfos.size(); i++) { 85 ListView.FixedViewInfo info = mFooterViewInfos.get(i); 86 if (info.view == v) { 87 mFooterViewInfos.remove(i); 88 89 mAreAllFixedViewsSelectable = 90 areAllListInfosSelectable(mHeaderViewInfos) 91 && areAllListInfosSelectable(mFooterViewInfos); 92 93 return true; 94 } 95 } 96 97 return false; 98 } 99 100 public int getCount() {101 if (mAdapter != null) {102 return getFootersCount() + getHeadersCount() + mAdapter.getCount();103 } else {104 return getFootersCount() + getHeadersCount();105 }106 }107 108 109 ......110 111 public Object getItem(int position) {112 // Header (negative positions will throw an ArrayIndexOutOfBoundsException)113 int numHeaders = getHeadersCount();114 if (position < numHeaders) {115 return mHeaderViewInfos.get(position).data;116 }117 118 // Adapter119 final int adjPosition = position - numHeaders;120 int adapterCount = 0;121 if (mAdapter != null) {122 adapterCount = mAdapter.getCount();123 if (adjPosition < adapterCount) {124 return mAdapter.getItem(adjPosition);125 }126 }127 128 // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)129 return mFooterViewInfos.get(adjPosition - adapterCount).data;130 }131 132 public long getItemId(int position) {133 int numHeaders = getHeadersCount();134 if (mAdapter != null && position >= numHeaders) {135 int adjPosition = position - numHeaders;136 int adapterCount = mAdapter.getCount();137 if (adjPosition < adapterCount) {138 return mAdapter.getItemId(adjPosition);139 }140 }141 return -1;142 }143 144 145 public View getView(int position, View convertView, ViewGroup parent) {146 // Header (negative positions will throw an ArrayIndexOutOfBoundsException)147 int numHeaders = getHeadersCount();148 if (position < numHeaders) {149 return mHeaderViewInfos.get(position).view;150 }151 152 // Adapter153 final int adjPosition = position - numHeaders;154 int adapterCount = 0;155 if (mAdapter != null) {156 adapterCount = mAdapter.getCount();157 if (adjPosition < adapterCount) {158 return mAdapter.getView(adjPosition, convertView, parent);159 }160 }161 162 // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)163 return mFooterViewInfos.get(adjPosition - adapterCount).view;164 }165 166 public int getItemViewType(int position) {167 int numHeaders = getHeadersCount();168 if (mAdapter != null && position >= numHeaders) {169 int adjPosition = position - numHeaders;170 int adapterCount = mAdapter.getCount();171 if (adjPosition < adapterCount) {172 return mAdapter.getItemViewType(adjPosition);173 }174 }175 176 return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;177 }178 179 public int getViewTypeCount() {180 if (mAdapter != null) {181 return mAdapter.getViewTypeCount();182 }183 return 1;184 }185 ......186 187 public Filter getFilter() {188 if (mIsFilterable) {189 return ((Filterable) mAdapter).getFilter();190 }191 return null;192 }193 //获取被包装的adapter,即我们设置的listView194 public ListAdapter getWrappedAdapter() {195 return mAdapter;196 }197 }
要获取到我们设置的adapter,这个方法是在接口中实现的,直接获取到即可
package android.widget;
1 /** 2 * List adapter that wraps another list adapter. The wrapped adapter can be retrieved 3 * by calling {@link #getWrappedAdapter()}. 4 * 5 * @see ListView 6 */ 7 public interface WrapperListAdapter extends ListAdapter { 8 /** 9 * Returns the adapter wrapped by this list adapter.10 *11 * @return The {@link android.widget.ListAdapter} wrapped by this adapter.12 */13 public ListAdapter getWrappedAdapter();14 }
android ListView 分析(一)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。