Android 分析监听器上的参数position和id

Android 分析监听器上的参数positionid

  Android API中有部分事件监听器的方法中都会有参数positionid,它们是用来描述一个视图当中的某一项(item,当然你也可以理解成其它的意思)的属性。position描述该项在视图中所处的位置;id描述的是该项的id,确切点说是该项在视图中所在的行位置。
  这就造成了一种困惑,我们在实际开发中,到底怎么去理解去这两个参数?我们又该怎么去使用?两者又何区别?
  下面以ListView中的onItemClickListener事件监听器为例,分析一下两者的区别及其如何使用。

 一、区别

  貌似有点复杂,分两种场景来讨论:
1.ListViewSimpleAdapter展示数据
position:表示该项在视图中的位置,起始为0
       id:
同上。
2.ListViewCursorAdapter展示数据 
       position:
同上。
id:表示该项在视图中实际位置,说白了就是起始为1。在视图上是第几行,就是第几行。举例:某个ListView共有5行数据,我选中了第3行,那么onItemClickListener()中的id就为3
3.源码分析
  上面简短的总结了两种场景下的含义,说再多也顶不上来自源码的分析:
  同样也分两种场景,我们先来分析CursorAdapter场景:
  是谁给参数positionid赋的值?

      android.widget.AbsListView
里面定义了一个私有内部类,用来处理ListView单击事件,参见下面源码:

Java代码:

1.   

2.  private class PerformClick extendsWindowRunnnable implements Runnable {

3.  View mChild;//子视图

4.  int mClickMotionPosition;//单击事件的所在位置(该位置应理解为某集合中的位置。)

5.  //执行主方法

6.  public void run() {

7.  if (mDataChanged) return;

8.  //这个是告知Android我们用哪个场景来展示数据。

9.  //SimpleAdapter还是CursorAdapter?

10. //阐述策略模式的一个真实场景。

11. final ListAdapter adapter =mAdapter;

12. //这个就是我们经常看到的position

13. final int motionPosition =mClickMotionPosition;

14. if (adapter != null &&mItemCount > 0 &&motionPosition != INVALID_POSITION &&

15. motionPosition <adapter.getCount() && sameWindow()) {

16.  

17. //positon还是原来的position,但id就不一样了,它是依靠position来计算得出的值。

18. //adapter getItemId(motionPosition)也说明了两种场景下的实现方式也是不一样的。

19. performItemClick(mChild,motionPosition, adapter.getItemId(motionPosition));

20. }

21. }

22.  

23. }

24.  

复制代码


     CursorAdapter场景中的id是怎样实现的?

Java代码:

1.  public long getItemId(int position){

2.  if (mDataValid && mCursor !=null) {

3.  //游标挪到了position的位置上。

4.  if(mCursor.moveToPosition(position)) {

5.  //参数mRowIDColumn就是主键ID位置,也就是上文所说的带有”_id”的字段的位置。

6.  returnmCursor.getLong(mRowIDColumn);

7.  } else {

8.  return 0;

9.  }

10. } else {

11. return 0;

12. }

13.  

14. }

15.  

16.  

复制代码


        android.database.CursorWindow
定义并实现了getLong(),参见下面源码:

Java代码:

1.  public long getLong(int row, intcol) {

2.  acquireReference();

3.  try {

4.  // getLong_native是本地方法,底层计算得出视图中我们单击的那个实际行位置

5.  //参数col就是上面提到的那个mRowIDColumn

6.  return getLong_native(row -mStartPos, col);

7.  } finally {

8.  releaseReference();

9.  }

10. }

11.  

12.  

复制代码


    SimpleAdapter场景中的id是怎样实现的?  了解了CursorAdapter场景的id实现方式,那么SimpleAdapter的实现方式就更容易了解了,非常简单,参见下面源码:

Java代码:

1.  public long getItemId(int position){

2.  //返回的就是position

3.  return position;

4.  }

5.   

 

 二、使用方式

  分两种场景,以代码的形式来展示使用方式,以下均选中第2行:

1.SimpleAdapter
      
模拟数据,其中_id类似于数据库中的主键,主键名一定要带有”_id”,Android好这口。虽然不是从数据库获取的数据,但最好也要遵从这种习惯。

Java代码:

1.  ArrayList> classic = newArrayList>();

2.  HashMap englishMap = new HashMap();

3.  englishMap.put(“classic_id”,1l);

4.  englishMap.put(“name”,lileilei);

5.  englishMap.put(“gender”,male);

6.  englishMap.put(“classic _id”,2l);

7.  englishMap.put(“name”,hanmeimei);

8.  englishMap.put(“gender”,female);

9.  englishMap.put(“classic _id”,3l);

10. englishMap.put(“name”,poly);

11. englishMap.put(“gender”,male);

12. //创建SimpleAdater

13. SimpleAdapter simpleAdapter = newSimpleAdapter(this, data, R.layout.classic,new String[] { " classic_id", "name", "age" }, new int[] {R.id.id_text,R.id.name_text, R.id.age_text });

14. //设置监听器

15. ListView lv =this.findViewById(R.id.listview);

16. lv.setAdapter(simpleAdapter);

17. lv.setOnItemClickListener(newOnItemClickListener() {

18.  

19. @Override

20. public void onItemClick(AdapterViewparent, View view,int position, long id) {

21. Log.i(LOG_TAG, "position:"+ position);//输出1

22. Log.i(LOG_TAG, "id:" +id);//输出1

23. Log.i(LOG_TAG, "item class :"+ ((ListView) parent).getItemAtPosition(position).getClass().getSimpleName());//输出item class : HashMap

24. //由于上面第三条日志信息输出的类型为HashMap,所以采用HashMap的方式获取数据。

25. HashMap englishMap = (HashMap)((ListView) parent).getItemAtPosition(position);

26. if (englishMap!= null &&englishMap.size()> 0) {

27. //做其他操作

28. }

29. }

30. });

31.  

32.  

 

       2. CursorAdapter
Java代码:

1.   

2.  //从数据库中获取数据,同样,返回的Cursor中必须含有”_id”的字段。

3.  Cursor cursor = .....;//写一个查询数据的方法并返回一个Cursor对象;

4.  //创建SimpleCursorAdapter

5.  SimpleCursorAdaptersimpleCursorAdapter = new SimpleCursorAdapter(this,R.layout.person, cursor, newString[] { " classic _id ", "name", "age" },newint[] { R.id.id_text, R.id.name_text, R.id.age_text });

6.  //设置监听器

7.  ListView lv =this.findViewById(R.id.listview);

8.  lv.setAdapter(simpleCursorAdapter);

9.  lv.setOnItemClickListener(newOnItemClickListener(){

10. @Override

11. public void onItemClick(AdapterViewparent, View view,int position, long id) {

12. Log.i(LOG_TAG, "position:"+ position);//输出1

13. Log.i(LOG_TAG, "id:" +id);//输出2

14. Log.i(LOG_TAG, "item class :"+ ((ListView) parent).getItemAtPosition(position).getClass().getSimpleName());

15. //输出item class : SQLiteCursor

16. //由于上面第三条日志信息输出的类型为SQLiteCursor,所以采用Cursor的方式获取数据。

17. Cursor cursor = (Cursor) ((ListView)parent).getItemAtPosition(position);

18. if (cursor != null &&cursor.moveToPosition(position)) {

19. //做其他操作

20. }

21. }

22.  

23. });

24.  

25.  


        
四、总结

  目前还是要重点使用positon为上策,更复合程序员的编程习惯(下标以0开始);id存在一定的变数,也许还未领会其实际用途吧,并且不太理解为什么id要是long类型的。
onItemClickListener()中的positionid就是这样实现的,那与之相类似的监听器也是如此。毕竟监听器是实际开发中经常用到的,所以弄懂细枝末节还是有必要的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值