转载地址:http://blog.iamzsx.me/show.html?id=147001

我们在使用ListView的时候,一般都会为ListView添加一个响应事件android.widget.AdapterView.OnItemClickListener。本文主要在于对OnItemClickListener的position和id参数做详细的解释,我相信有些人在这上面走了些弯路。

先来看一下官方的文档
position The position of the view in the adapter.
id The row id of the item that was clicked.
而这两行字并没有解释清楚position和id的区别。另外,我们还有个Adapter的getView方法。

public abstract View getView (int position, View convertView, ViewGroup parent)

这里也有一个position。
 
初步接触ListView的同学,一般会直接继承ArrayAdapter,然后(比如我),就想当然的认为OnItemClick的position和getView的position是一样的啊。于是我们就getItem(position)来获取相应的数据。
 
那么这段代码有没有错呢?如果有错的话,在什么情况会出错呢?
第一个问题的答案是,当我们为ListView添加headerView或者footerView之后,这段代码就不一定是我们想要的了。
 
出现问题的原因在于,当我们为ListView添加headerView或者footerView之后,ListView在setAdapter时,做了一些事情,这导致,Adapter和OnItemClickListener中的position含义发生了变化。
 
我们可以来看看ListView中setAdapter的实现
437  public void setAdapter(ListAdapter adapter) {
438 if (mAdapter != null && mDataSetObserver != null) {
439 mAdapter.unregisterDataSetObserver(mDataSetObserver);
440 }
442 resetList();
443 mRecycler.clear();
445 if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
446 mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
447 } else {
448 mAdapter = adapter;
449 }
可以看出,如果这个ListView存在headerView或者footerView的话,那么会在我们传入的adapter外面在封装一层HeaderViewListAdapter,这是一个专门用来自动处理headerView和footerView的adapter。在ListView中,本身不区分headerView,footerView。ListView可以理解成是只负责管理一组View的数组的UI(ViewGroup),headerView和footerView都委托给HeaderViewListAdapter来处理。(从这里也可以看到为什么API文档中提到,addFooterView和addHeaderView要在setAdapter函数之前调用,如果在之后调用,那么就不会生成HeaderViewListAdapter,从而导致显示不出headerView和footerView)。
 
回到开头的问题,position和id有啥区别。为此,我们找一下position和id是怎么传进来的。
OnItemClickListener在android.widget.AdapterView的public boolean performItemClick(View view, int position, long id)函数中被调用。
performItemClick在android.widget.AbsListView.PerformClick.run() 中被调用
2497  private class PerformClick extends WindowRunnnable implements Runnable {
2498 int mClickMotionPosition;
2500 public void run() {
2501 // The data has changed since we posted this action in the event queue,
2502 // bail out before bad things happen
2503 if (mDataChanged) return;
2505 final ListAdapter adapter = mAdapter;
2506 final int motionPosition = mClickMotionPosition;
2507 if (adapter != null && mItemCount > 0 &&
2508 motionPosition != INVALID_POSITION &&
2509 motionPosition < adapter.getCount() && sameWindow()) {
2510 final View view = getChildAt(motionPosition - mFirstPosition);
2511 // If there is no view, something bad happened (the view scrolled off the
2512 // screen, etc.) and we should cancel the click
2513 if (view != null) {
2514 performItemClick(view, motionPosition, adapter.getItemId(motionPosition));
2515 }
2516 }
2517 }
2518 }
可以看到,position事实上就是ListView中被点击的view的位置。注意,在ListView中是不负责处理headerView和footViewer的,所以,这个位置应该是这个被点击的view在数组[所有的headerView,用户添加的view,所有的footerView]中的位置(请自行参考HeaderViewListAdapter的getView实现)。而id是来自于adapter.getItemId(position)。
 
对于ArrayAdapter的getItemId函数,实现就是return position。id和position是一致的。
然而,对于HeaderViewListAdapter

 
188  public long getItemId(int position) {
189 int numHeaders = getHeadersCount();
190 if (mAdapter != null && position >= numHeaders) {
191 int adjPosition = position - numHeaders;
192 int adapterCount = mAdapter.getCount();
193 if (adjPosition < adapterCount) {
194 return mAdapter.getItemId(adjPosition);
195 }
196 }
197 return -1;
198 }
 
实现逻辑是,如果position指向了headerView或footerView,那么返回-1,否则,将返回在用户view数组的位置。
也就是说
id=position-headerView的个数(id < headerviewer的个数+用户view的个数),否则=-1
因此,OnItemClickListener的正确实现如下:
void onItemClick(AdapterViewparent, View view, int position, long id){
if(id<) {
// 点击的是headerView或者footerView
return;
}
int realPosition=(int)id;
T item=getItem(realPosition);
// 响应代码
}
 

OnItemClickListener 的参数详解(转)的更多相关文章

  1. Nginx主配置参数详解,Nginx配置网站

    1.Niginx主配置文件参数详解 a.上面博客说了在Linux中安装nginx.博文地址为:http://www.cnblogs.com/hanyinglong/p/5102141.html b.当 ...

  2. iptables参数详解

    iptables参数详解 搬运工:尹正杰 注:此片文章来源于linux社区. Iptalbes 是用来设置.维护和检查Linux内核的IP包过滤规则的. 可以定义不同的表,每个表都包含几个内部的链,也 ...

  3. chattr的常用参数详解

    chattr的常用参数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在实际生产环境中,有的运维工程师不得不和开发和测试打交道,在我们公司最常见的就是部署接口.每天每个人部署的 ...

  4. mha配置参数详解

    mha配置参数详解: 参数名字 是否必须 参数作用域 默认值 示例 hostname Yes Local Only - hostname=mysql_server1, hostname=192.168 ...

  5. $.ajax()方法所有参数详解;$.get(),$.post(),$.getJSON(),$.ajax()详解

    [一]$.ajax()所有参数详解 url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注 ...

  6. linux PHP 编译安装参数详解

    linux PHP 编译安装参数详解 ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc -- ...

  7. 【转】jqGrid 各种参数 详解

      [原文]http://www.cnblogs.com/younggun/archive/2012/08/27/2657922.htmljqGrid 各种参数 详解 JQGrid JQGrid是一个 ...

  8. HTML滚动字幕代码参数详解及Js间隔滚动代码

    html文字滚动代码 <marquee style="WIDTH: 388px; HEIGHT: 200px" scrollamount="2" dire ...

  9. mysql5.6主从参数详解

    mysql5.6的主从相当的不错,增加了不少参数,提升了主从同步的安全和效率,以下是mysql5.6主从参数详解. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

随机推荐

  1. lintcode 中等题:digits counts 统计数字

    题目 统计数字 计算数字k在0到n中的出现的次数,k可能是0~9的一个值 样例 例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现 ...

  2. SaaS系列介绍之十二: SaaS产品的研发模式

    1 产品研发模式慨述 产品研发模式是企业战略的重点.产品研发路线决定了一系列的管理手段和团队建设问题.也是企业的整理策略和经营思路.产品研发模式贯穿着整个产品的生命周期,从市场调研.立项.需求分析.慨 ...

  3. asp.net中几个网页跳转的方法及区别

    1:注意:Response.Redirect("a.html")是不能跳出框架.IFRAME的. 可以使用 Response.Write("<script Lang ...

  4. [转]c#调用API截图

    转自http://blog.csdn.net/hailiannanhai/article/details/6281471 要想完成这个功能,首先要了解一下在C#中如何调用API(应用程序接口)函数.虽 ...

  5. Java学习笔记之:Java数组

    一.介绍 数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同. Java语言中提供的数组是用来存储固定大小的同类型元素. 你可以声明一个数组变量,如number ...

  6. Hibernate逍遥游记-第9章 Hibernate的映射类型

    1. 2. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate ...

  7. NewPascal(也许只是对FreePascal的一种封装)

    NewPascal is a breath of fresh air and long tradition! NewPascal offers a ready-to-be-used and up-to ...

  8. QT里使用sqlite的问题,好多坑

    1. 我使用sqlite,开发机上好好的,测试机上却不行.后来发现是缺少驱动(Driver not loaded Driver not loaded),代码检查了又检查,发现应该是缺少dll文件(系统 ...

  9. tomcat中如何运行war包呢

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPQAAADRCAIAAAB0LAgsAAAQtklEQVR4nO2d7W/bxh3H9ZfZbRrFOj

  10. Android线性布局(Linear Layout)

    Android线性布局(Linear Layout) LinearLayout是一个view组(view group),其包含的所有子view都以一个方向排列,垂直或是水平方向.我们能够用androi ...