需要了解的内容
1. listview中的getItemAtPosition与Adapter的getItem的position的区别 
        listView中的getItemAtPosition的源码实现:
 /**
* Gets the data associated with the specified position in the list.
*
* @param position Which data to get
* @return The data associated with the specified position in the list
*/
public Object getItemAtPosition(int position) {
T adapter = getAdapter();
return (adapter == null || position < 0) ? null : adapter.getItem(position);
} public long getItemIdAtPosition(int position) {
T adapter = getAdapter();
return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position);
}
 
如果在adapter部位null并且position不是负数的时候,那么就会直接调用listView中真正的adapter的getItem()方法
 
因而我们自己定义的adapter,其实和listView中定义的getItemAtPosition()存在的差异就是在有headView和footView的时候
 
但是在我们自己的adapter中还是应该用有效的position
而在外部想直接调用的时候,应该让listView.getAdapter().getItem(position),如果调用到了headView或者footView的时候,那么就是返回为空的,因为在包装的
那么就是调用的headViewInfo中的data或者mFooterViewInfos.data
 public Object getItem(int position) {
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return mHeaderViewInfos.get(position).data;
} // Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItem(adjPosition);
}
} // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).data;
}
这个算是简单的View的包装器
/**
* A class that represents a fixed view in a list, for example a header at the top
* or a footer at the bottom.
*/
public class FixedViewInfo {
/** The view to add to the list */
public View view;
/** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */
public Object data;
/** <code>true</code> if the fixed view should be selectable in the list */
public boolean isSelectable;
}
  
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
 
查看源码便得知
 /**
* Sets the data behind this ListView.
*
* The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},
* depending on the ListView features currently in use. For instance, adding
* headers and/or footers will cause the adapter to be wrapped.
*
* @param adapter The ListAdapter which is responsible for maintaining the
* data backing this list and for producing a view to represent an
* item in that data set.
*
* @see #getAdapter()
*/
@Override
public void setAdapter(ListAdapter adapter) {
if (null != mAdapter) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
} resetList();
mRecycler.clear();
//关键代码 ListView 在 存在headView或者footView的时候,listView设置的adapter并不是我们设置的adapter,而是包装过的HeaderViewListAdapter if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
} ......
}
既然如此设计,那么在使用的时候,我们便需要注意一些细节
listView中获取的getItemAtPosition中的position并不一定和我们的adapter的position相同
 
因而在设置position的时候,需要将position进行处理
例如
onItemClick中,传递而来的position有可能是包裹后的,因而我们考虑手工去除或者让系统来去除,即将包裹后的position转换为我们的adapter的position
 
1.手工方式
 listView.setOnItemClickListener(new OnItemClickListener() {

 @Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
int realPosition = position - listView.getHeaderViewsCount();
}
});
2. 调用系统api的方式(推荐使用的方式)
 
在设置listView的相关监听的时候,会提供AdapterView<?> parent这个参数,这个其实就是我们的listView
调用他的getAdapter()获取到实际的adapter,然后调用adapter的获取数据的方式
 
 @Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
doSomething(parent.getAdapter().getItem(position));
}
 扩展内容,包裹的adapter --> HeaderViewListAdapter

 ......
import java.util.ArrayList; /**
* ListAdapter used when a ListView has header views. This ListAdapter
* wraps another one and also keeps track of the header views and their
* associated data objects.
*<p>This is intended as a base class; you will probably not need to
* use this class directly in your own code.
*/
public class HeaderViewListAdapter implements WrapperListAdapter, Filterable { private final ListAdapter mAdapter; // These two ArrayList are assumed to NOT be null.
// They are indeed created when declared in ListView and then shared.
ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
ArrayList<ListView.FixedViewInfo> mFooterViewInfos; // Used as a placeholder in case the provided info views are indeed null.
// Currently only used by some CTS tests, which may be removed.
static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST =
new ArrayList<ListView.FixedViewInfo>();
...... public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,
ArrayList<ListView.FixedViewInfo> footerViewInfos,
ListAdapter adapter) {
mAdapter = adapter;
mIsFilterable = adapter instanceof Filterable; if (headerViewInfos == null) {
mHeaderViewInfos = EMPTY_INFO_LIST;
} else {
mHeaderViewInfos = headerViewInfos;
} if (footerViewInfos == null) {
mFooterViewInfos = EMPTY_INFO_LIST;
} else {
mFooterViewInfos = footerViewInfos;
} mAreAllFixedViewsSelectable =
areAllListInfosSelectable(mHeaderViewInfos)
&& areAllListInfosSelectable(mFooterViewInfos);
} public int getHeadersCount() {
return mHeaderViewInfos.size();
} public int getFootersCount() {
return mFooterViewInfos.size();
} public boolean isEmpty() {
return mAdapter == null || mAdapter.isEmpty();
} ...... public boolean removeHeader(View v) {
for (int i = 0; i < mHeaderViewInfos.size(); i++) {
ListView.FixedViewInfo info = mHeaderViewInfos.get(i);
if (info.view == v) {
mHeaderViewInfos.remove(i); mAreAllFixedViewsSelectable =
areAllListInfosSelectable(mHeaderViewInfos)
&& areAllListInfosSelectable(mFooterViewInfos); return true;
}
} return false;
} public boolean removeFooter(View v) {
for (int i = 0; i < mFooterViewInfos.size(); i++) {
ListView.FixedViewInfo info = mFooterViewInfos.get(i);
if (info.view == v) {
mFooterViewInfos.remove(i); mAreAllFixedViewsSelectable =
areAllListInfosSelectable(mHeaderViewInfos)
&& areAllListInfosSelectable(mFooterViewInfos); return true;
}
} return false;
} public int getCount() {
if (mAdapter != null) {
return getFootersCount() + getHeadersCount() + mAdapter.getCount();
} else {
return getFootersCount() + getHeadersCount();
}
} ...... public Object getItem(int position) {
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return mHeaderViewInfos.get(position).data;
} // Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItem(adjPosition);
}
} // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).data;
} public long getItemId(int position) {
int numHeaders = getHeadersCount();
if (mAdapter != null && position >= numHeaders) {
int adjPosition = position - numHeaders;
int adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemId(adjPosition);
}
}
return -1;
} public View getView(int position, View convertView, ViewGroup parent) {
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return mHeaderViewInfos.get(position).view;
} // Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getView(adjPosition, convertView, parent);
}
} // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).view;
} public int getItemViewType(int position) {
int numHeaders = getHeadersCount();
if (mAdapter != null && position >= numHeaders) {
int adjPosition = position - numHeaders;
int adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemViewType(adjPosition);
}
} return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
} public int getViewTypeCount() {
if (mAdapter != null) {
return mAdapter.getViewTypeCount();
}
return 1;
}
...... public Filter getFilter() {
if (mIsFilterable) {
return ((Filterable) mAdapter).getFilter();
}
return null;
}
//获取被包装的adapter,即我们设置的listView
public ListAdapter getWrappedAdapter() {
return mAdapter;
}
}
 
要获取到我们设置的adapter,这个方法是在接口中实现的,直接获取到即可
package android.widget;
 
 /**
* List adapter that wraps another list adapter. The wrapped adapter can be retrieved
* by calling {@link #getWrappedAdapter()}.
*
* @see ListView
*/
public interface WrapperListAdapter extends ListAdapter {
/**
* Returns the adapter wrapped by this list adapter.
*
* @return The {@link android.widget.ListAdapter} wrapped by this adapter.
*/
public ListAdapter getWrappedAdapter();
}

 安卓源码分析群: Android源码分析QQ1群号:164812238

android ListView 分析(一)的更多相关文章

  1. android ListView 九大重要属性详细分析、

    android ListView 九大重要属性详细分析. 1.android ListView 一些重要属性详解,兄弟朋友可以参考一下. 首先是stackFromBottom属性,这只该属性之后你做好 ...

  2. Android ListView异步载入图片乱序问题,原因分析及解决方式

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/45586553 在Android全部系统自带的控件其中,ListView这个控件算是 ...

  3. Android ListView滑动过程中图片显示重复错乱闪烁问题解决

    最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及L ...

  4. [转] Android 性能分析案例

    Android 系统的一个工程师(Romain Guy)针对Falcon Pro  应用,撰写了一个Android性能分析的文章.该文章介绍了如何分析一个应用哪里出现了性能瓶颈,导致该应用使用起来不流 ...

  5. Android 演示 Android ListView 和 github XListView(3-3)

    本文内容 环境 项目结构 演示 1:简单 XListView 演示 2:XListView + Fragment 演示 3:XListView + ViewPager + Fragment 本文三个演 ...

  6. Android 演示 Android ListView 和 github XListView(1-3)

    本文内容 环境 项目结构 演示 1:ListView 演示 2:简单 XListView 演示 3:音乐列表 XListView 演示 4:另一个音乐列表 XListView 本文四个演示,循序渐进. ...

  7. Android ListView工作原理完全解析,带你从源码的角度彻底理解

    版权声明:本文出自郭霖的博客,转载必须注明出处.   目录(?)[+] Adapter的作用 RecycleBin机制 第一次Layout 第二次Layout 滑动加载更多数据   转载请注明出处:h ...

  8. Android ListView工作原理全然解析,带你从源代码的角度彻底理解

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android全部经常使用的原生控件其中.使用方法最复杂的应该就是 ...

  9. 老潘 - ListView分析 - 学以致用篇(一)

    ListView分析学以致用篇(1) 在我们查看别人的博客的时候,一个人是一个风格的.先说下我的风格,我喜欢思想类比,然后介绍知识,不太喜欢填鸭式的灌输.如果只是想单纯的从我的博客中直接看到代码,我个 ...

随机推荐

  1. 【iOS系列】-触摸事件与手势识别

    [iOS系列]-触摸事件与手势识别 第一:触摸事件 一根手指触摸屏幕时,会创建一个与手指相关联的UITouch对象 UIEvent:称为事件对象,记录事件产生的时刻和类型 两根手指同时触摸一个view ...

  2. NYOJ1026 阶乘末尾非0 【模板】

    阶乘末尾非0 时间限制:2000 ms  |  内存限制:65535 KB 难度:3 描写叙述 我们的问题非常是简单.n! 末尾非0数是几? 比方n=5的时候,n! =120,那么n!末尾非0数是2. ...

  3. C项目实践之通讯录管理案例

    1.功能需求分析 通讯录管理案例主要实现对联系人的信息进行添加.显示.查找.删除.更新和保存功能.主要功能需求描述如下: (1)系统主控平台: 充许用户选择想要进行的操作,包括添加联系人信息,显示.查 ...

  4. visio 2010 修改 默认字体 字号大小 方法[整理]

    [转自]http://www.cnblogs.com/vegaliming/archive/2012/08/09/2630568.html 1.新建一个模具 2.将常用的图形放到这个模具中 3.对每个 ...

  5. test_action

    [TOP] 为什么百度校招数据挖掘工程师的笔试题目是跟数据挖掘关系不大? - 研究生生活交流 - 王道论坛,专注于计算机考研的点点滴滴! http://www.cskaoyan.com/thread- ...

  6. Lightoj 1024 - Eid

    求n个数的最小公倍数. import java.math.*; import java.io.*; import java.util.*; import java.text.*; public cla ...

  7. Ubuntu 12.04 make menuconfig 出现 Unable to find the ncurses libraries or the required header files.

    问题: *** Unable to find the ncurses libraries or the *** required header files. *** 'make menuconfig' ...

  8. UltraEdit mac破解版

    2018-01-17 增加18.00.0.19破解 去官网下载原载,先运行一次,再在终端里执行下面代码就可以破解完成! printf '\x31\xC0\xFF\xC0\xC3\x90' | dd s ...

  9. AutoIT: 如何设置GUICtrlCreateCombo选项为不可修改状态

    GUICtrlCreateCombo中选中的选项是可修改的,也可设置为不可修改状态. #include<ComboConstants.au3> GUICtrlCreateLabel(, , ...

  10. ubuntu搭建开发环境踩坑实录

    谨以此文,记录和ubuntu系统不死不休的搏斗过程,后续待补. 1.双系统安装,windows采用uefi模式安装(优启通可制作uefi的win10安装盘),ubuntu不要划分boot区,而应该划分 ...