做Android开发,ListView是最常见不过了,因此对于ListView的自定义Adapter写法,应该也非常的熟悉,高效的Adapter编码,会使得携带大量ListView的数据展现显得非常容易。关于Adapter的写法,网上也有很多的例子,在此不再唠叨。为了提高ListView重绘时对已有对象的复用大抵是这样的:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = View.inflate(mContext, R.layout.listview_item, null);
holder = new ViewHolder();
holder.no = (TextView) convertView.findViewById(R.id.no);
holder.click = (TextView) convertView.findViewById(R.id.click);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String value = list.get(position);
holder.no.setText(value);
OnClick listener = new OnClick(position);
holder.click.setOnClickListener(listener);
Log.d(TAG,
"position is " + position + " listener is "
+ listener.toString());
return convertView;
}
在这里我们讨论的是在ListView当中含有需要处理OnClick事件的写法,之前也写过一篇
关于ListView当中含有Spinner的处理情况,这篇文章讲了如何处理Spinner的Onlick事件和对其状态的保持。虽然Onclick事件处理的比较高效,但是在方法上还有待提高。以下文章将列举出网上关于ListView中含有Onclick事件需要处理的普遍写法和本文的重点推荐高效写法。
普遍写法:
package com.yang.listviewclick.adapter;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.yang.listviewclick.R;
public class IneffectiveListViewAdapter extends BaseAdapter {
private Context mContext;
private List<String> list = null;
private static final String TAG = "ListViewAdapter";
public IneffectiveListViewAdapter(Context mContext, List<String> list) {
this.mContext = mContext;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
class ViewHolder {
TextView no;
TextView click;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = View.inflate(mContext, R.layout.listview_item, null);
holder = new ViewHolder();
holder.no = (TextView) convertView.findViewById(R.id.no);
holder.click = (TextView) convertView.findViewById(R.id.click);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String value = list.get(position);
holder.no.setText(value);
//问题出在这里,对于每次重绘,都新建了一个listener对象进行处理
OnClick listener = new OnClick(position);
holder.click.setOnClickListener(listener);
Log.d(TAG,
"position is " + position + " listener is "
+ listener.toString());
return convertView;
}
class OnClick implements OnClickListener {
private int position;
public OnClick(int position){
this.position = position;
}
@Override
public void onClick(View v) {
Log.d(TAG, list.get(position));
}
}
}
这种写法能够实现基本功能,即在点击某个组件时,它能够准确的定位到所点击的那个条目,并作出相应的处理。那么这是一种高效的写法吗?我们打印以下它的listener.
大家知道
position is 19 listener is com.yang.listviewclick.adapter.IneffectiveListViewAdapter$OnClick@4057f250
@后面的值是这个对象的HashCode,对于不同的对象来说,其
HashCode是不同的,而这里打印出来的所有HashCode都不相同,说明每次拖动ListView,其会对每个条目重新申请一个对象,而且这些对象不是复用的,是全新的对象。你可以想象以下,如果有一千个条目,这拖动一次就是一千个对象,而且你再回到顶部又是一千个对象,效率可见一斑。
推荐写法:
package com.yang.listviewclick.adapter;
import java.util.List;
import com.yang.listviewclick.R;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class EffectiveListViewAdapter extends BaseAdapter {
private Context mContext;
private List<String> list = null;
private static final String TAG = "ListViewAdapter";
public EffectiveListViewAdapter(Context mContext, List<String> list) {
this.mContext = mContext;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
class ViewHolder {
TextView no;
TextView click;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
OnClick listener = null;
if (convertView == null) {
convertView = View.inflate(mContext, R.layout.listview_item, null);
holder = new ViewHolder();
holder.no = (TextView) convertView.findViewById(R.id.no);
holder.click = (TextView) convertView.findViewById(R.id.click);
listener = new OnClick();//在这里新建监听对象
holder.click.setOnClickListener(listener);
convertView.setTag(holder);
convertView.setTag(holder.click.getId(), listener);//对监听对象保存
} else {
holder = (ViewHolder) convertView.getTag();
listener = (OnClick) convertView.getTag(holder.click.getId());//重新获得监听对象
}
String value = list.get(position);//设置监听对象的值
holder.no.setText(value);
listener.setPosition(position);
Log.d(TAG,
"position is " + position + " listener is "
+ listener.toString());
return convertView;
}
class OnClick implements OnClickListener {
int position;
public void setPosition(int position) {
this.position = position;
}
@Override
public void onClick(View v) {
Log.d(TAG, list.get(position));
}
}
}
打印以下Listener
大家可以看到,这里监听对象实现了复用。每次滑动都是第一次创建的监听对象的复用。
实现这种机制的关键就是,使用convertView.setTag(holder.click.getId(), listener);对已有的对象进行保存,同时在使用时,使用listener = (OnClick) convertView.getTag(holder.click.getId())再获得这些对象。同时对这些复用的对象赋予不同的值listener.setPosition(position);。好了,今天就说到这里,测试项目的下载地址如下。
分享到:
相关推荐
在Adapter中,我们通常会创建一个自定义的布局文件,该文件包含了ListView每一项应有的组件,比如文本、图片或者按钮。 接着,我们会在Adapter的`getView()`方法中实例化并配置每个item的视图。在这个过程中,我们...
如果需要记录哪个Button被点击,可以在Adapter中维护一个状态数组,与ListView的项位置相对应。 最后,在Activity或Fragment中,我们需要实例化并设置这个Adapter到ListView上: ```java ListView listView = ...
3. **传递接口**:将父组件作为参数传递给ListView的Adapter,在Adapter中,当Button被点击时,调用这个接口的方法,从而触发父组件的回调。 代码示例: ```java public interface OnItemClickListener { void ...
在这个Adapter中,我们需要重写`getView()`方法来为ListView的每个条目生成视图。在这个过程中,我们可以在每个条目中添加一个Button。例如: ```java public class ListViewAdapter extends BaseAdapter { // ......
在这个Adapter中,你需要重写`getView()`方法,这是为ListView的每个列表项生成视图的地方。 ```java public class MyListAdapter extends BaseAdapter { private Context context; // 数据源 private List...
在本示例中,我们关注的是如何在ListView中集成Button控件,并通过自定义Adapter来实现这一功能。这涉及到Android UI设计、数据绑定和事件处理等多个方面。 首先,我们了解ListView的基本原理。ListView通过Adapter...
在这个Adapter中,我们需要重写`getView()`方法,该方法负责为ListView的每一项创建并返回一个View对象。在`getView()`中,我们可以实例化并配置每个Item中的Button,包括设置初始的背景、文字等属性。 接着,为了...
你可以仿照上述步骤,修改`list_item.xml`布局,将Button替换为ImageButton,然后在Adapter中相应地处理图片的设置和点击事件。 总结来说,ListView的基本使用包括创建ListView、定义条目布局、创建Adapter并实现...
为了增强用户体验和功能,我们有时需要在ListView的每个列表项中添加其他组件,比如Button。本篇将详细介绍如何在ListView中添加Button,自定义布局,并获取输入框中的值。 首先,我们需要创建一个自定义的布局文件...
当我们需要在每个列表项中添加交互元素,如Button,来提供用户操作,那么就需要对ListView进行自定义。本篇文章将详细讲解如何在Android的ListView中添加Button,并实现其点击事件。 首先,我们要创建一个自定义的...
动态加载ListView是指在用户触发特定事件(如点击Button)时,程序按需加载数据到ListView中,而不是一次性加载所有数据,这样可以提高应用的性能和用户体验。本文将详细讲解如何实现“点击button动态加载listView”...
本教程将详细介绍如何在ListView中实现点击特定Item的Button时,动态地改变该Button的文字(Text)和背景颜色。 首先,我们需要创建一个自定义的ListView项布局(list_item.xml)。这个布局文件通常会包含一个...
在Adapter中,我们创建了一个ViewHolder类来缓存视图,避免频繁的findViewById操作。同时,我们为增加和减少按钮设置了点击监听器,并将对应的数据对象(ItemData)作为Tag保存,这样在点击事件中可以通过Tag获取到...
2. **自定义Adapter**:在Adapter的getView()方法中,为每个ListView项中的Button设置点击监听器,并阻止事件传播。这样,每次创建新的ListView项时,都会确保Button的点击事件能够正确处理。 ```java @Override ...
在Android开发中,ListView是一种常用的视图组件,用于展示大量数据列表。为了增强用户体验和交互性,我们常常会在ListView的每一项(Item)中添加按钮。这样,用户可以通过点击按钮来执行特定的操作,如查看详情、...
在Adapter中,我们重写`getView()`方法,该方法用于为ListView的每一项生成视图。在这个方法中,我们可以找到并初始化ListView Item中的按钮,并为其设置点击事件监听器。 2. **实现接口回调**: 在Adapter中定义...
在Adapter中,你需要重写以下方法: - `getCount()`:返回数据集的大小。 - `getItem(int position)`:返回指定位置的数据对象。 - `getItemId(int position)`:返回指定位置的数据ID,通常返回位置值。 - `...
而当我们在ListView的每一项中加入Button时,可能会遇到一些交互上的挑战,即如何正确处理Button的点击事件,使得用户操作能够得到准确响应。这个问题的核心在于ListView的复用机制,因为ListView为了提高性能,会...
本文将深入探讨如何在ListView中添加图片和按钮,并实现它们以及ListView的双监听,以便按钮点击时能触发Activity的跳转。 首先,我们需要创建一个自定义的ListView适配器,通常会继承自BaseAdapter。在这个适配器...