Android API中有部分事件监听器的方法中都会有参数position和id,它们是用来描述一个视图当中的某一项(item,当然你也可以理解成其它的意思)的属性。position描述该项在视图中所处的位置;而id描述的是该项的id,确切点说是该项在视图中所在的行位置。
这就造成了一种困惑,我们在实际开发中,到底怎么去理解去这两个参数?我们又该怎么去使用?两者又何区别?
下面以ListView中的onItemClickListener事件监听器为例,分析一下两者的区别及其如何使用。
一、区别
貌似有点复杂,分两种场景来讨论:
1.ListView用SimpleAdapter展示数据
position:表示该项在视图中的位置,起始为0。
id:同上。
2.ListView用CursorAdapter展示数据
position: 同上。
id:表示该项在视图中实际位置,说白了就是起始为1。在视图上是第几行,就是第几行。举例:某个ListView共有5行数据,我选中了第3行,那么onItemClickListener()中的id就为3。
3.源码分析
上面简短的总结了两种场景下的含义,说再多也顶不上来自源码的分析:
同样也分两种场景,我们先来分析CursorAdapter场景:
是谁给参数position和id赋的值?
android.widget.AbsListView里面定义了一个私有内部类,用来处理ListView单击事件,参见下面源码:
- private class PerformClick extends WindowRunnnable implements Runnable {
- View mChild;
- int mClickMotionPosition;
-
- public void run() {
- if (mDataChanged) return;
-
-
-
- final ListAdapter adapter = mAdapter;
-
- final int motionPosition = mClickMotionPosition;
- if (adapter != null && mItemCount > 0 &&
- motionPosition != INVALID_POSITION &&
- motionPosition < adapter.getCount() && sameWindow()) {
-
-
- performItemClick(mChild, motionPosition, adapter.getItemId(motionPosition));
- }
- }
- }
CursorAdapter场景中的id是怎样实现的?
- public long getItemId(int position) {
- if (mDataValid && mCursor != null) {
-
- if (mCursor.moveToPosition(position)) {
-
- return mCursor.getLong(mRowIDColumn);
- } else {
- return 0;
- }
- } else {
- return 0;
- }
- }
android.database.CursorWindow定义并实现了getLong(),参见下面源码:
- public long getLong(int row, int col) {
- acquireReference();
- try {
-
-
- return getLong_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
SimpleAdapter场景中的id是怎样实现的?
了解了CursorAdapter场景的id实现方式,那么SimpleAdapter的实现方式就更容易了解了,非常简单,参见下面源码:
- public long getItemId(int position) {
-
- return position;
- }
二、使用方式
分两种场景,以代码的形式来展示使用方式,以下均选中第2行:
1.SimpleAdapter
-
- ArrayList<HashMap<String, String>> classic = new ArrayList<HashMap<String, String>>();
- HashMap<String, String> englishMap = new HashMap<String, String>();
- englishMap.put(“classic_id”,1l);
- englishMap.put(“name”,lileilei);
- englishMap.put(“gender”,male);
- englishMap.put(“classic _id”,2l);
- englishMap.put(“name”,hanmeimei);
- englishMap.put(“gender”,female);
- englishMap.put(“classic _id”,3l);
- englishMap.put(“name”,poly);
- englishMap.put(“gender”,male);
-
-
- SimpleAdapter simpleAdapter = new SimpleAdapter(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 });
-
-
- ListView lv = this.findViewById(R.id.listview);
- lv.setAdapter(simpleAdapter);
- lv.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view,
- int position, long id) {
- Log.i(LOG_TAG, "position:" + position);
- Log.i(LOG_TAG, "id:" + id);
- Log.i(LOG_TAG, "item class : "+ ((ListView) parent).getItemAtPosition(position).getClass().getSimpleName());
-
-
- HashMap<String, String> englishMap = (HashMap<String, String>) ((ListView) parent).getItemAtPosition(position);
- if (englishMap!= null && englishMap.size()> 0) {
-
- }
- }
- });
2. CursorAdapter
-
- Cursor cursor = .....;
-
- SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(this,R.layout.person, cursor, new String[] { " classic _id ", "name", "age" },new int[] { R.id.id_text, R.id.name_text, R.id.age_text });
-
-
- ListView lv = this.findViewById(R.id.listview);
- lv.setAdapter(simpleCursorAdapter);
- lv.setOnItemClickListener(newOnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
- Log.i(LOG_TAG, "position:" + position);
- Log.i(LOG_TAG, "id:" + id);
- Log.i(LOG_TAG, "item class : "+ ((ListView) parent).getItemAtPosition(position).getClass().getSimpleName());
-
-
- Cursor cursor = (Cursor) ((ListView) parent).getItemAtPosition(position);
- if (cursor != null && cursor.moveToPosition(position)) {
-
- }
- }
- });
四、总结
目前还是要重点使用positon为上策,更复合程序员的编程习惯(下标以0开始);而id存在一定的变数,也许还未领会其实际用途吧,并且不太理解为什么id要是long类型的。
onItemClickListener()中的position和id就是这样实现的,那与之相类似的监听器也是如此。毕竟监听器是实际开发中经常用到的,所以弄懂细枝末节还是有必要的。
五
自己的总结,在 onItemClick( AdapterView<?> parent, View view, int position, long id) 中,如果想获得ArrayList里的内容,那么就将list声明为成员变量,然后onItemclick中调用list.get(position)就是期望得到的map了。