[Android]在Adapter的getView方法中绑定OnClickListener比较好的方法
以下内容为原创,欢迎转载,转载请注明
来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4146512.html
给ListView中每个item绑定点击事件的方法,比较常见的如下这种方式:
public View getView(int positon, View convertView, ViewGroup parent){
if(null == convertView){
convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
} Button button = ABViewUtil.obtainView(convertView, R.id.item_btn);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Toast.makeText(context, "position: " + position, Toast.LENGTH_SHORT).show();
}
}); }
然后运行,当然没问题。
但是这里有一个可以优化的地方,注意代码第7行,每次调用getView方法都会设置Button的OnClickListener,会生成很多不必要的OnClickListener对象。
所以,我们可以想到,在生成convertView时,同时设置Button的OnClickListener,convertView是被不断地复用的,这样的OnClickListener也就可以被不断地服用,也就是说在第3行和第4行之间进行这一步。这样,代码演化到如下:
public View getView(int positon, View convertView, ViewGroup parent){
if(null == convertView){
convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
Button button = ABViewUtil.obtainView(convertView, R.id.item_btn);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Toast.makeText(context, "position: " + position, Toast.LENGTH_SHORT).show();
}
});
}
}
这个代码看上去没什么问题,但是问题就在onClick回调的的第8行中使用的position的时候,因为这里使用的是匿名内部类(这个匿名内部类实现了View.OnClickListener这个接口),所以如果需要在onClick中使用position这个变量的话,需要把position声明为final。一旦声明了final,等到编译之后,这个position就会被作为这个匿名内部类中的一个private的成员变量。这样,ListView往下滚动,下面需要显示的item会重用上面不显示的convertView,convertView中的Button设置的OnClickListener实现类的对象,回调onClick时,使用的position其实是该OnClickListener实现类的成员变量position(这个position的值只是在构造的时候被初始化了而已!)。所以,这个ListView刚加载完数据后,还未滚动时,点击屏幕上的item都是正常的,但是如果一旦滚动,有view被重用了,这个时候,position的值就错乱了,所以在onClick中通过position获取到的item的数据当然也是错乱的了。
所以,要解决这个问题,就需要让onClick方法回调的时候得到的position是个正确的值,我们可以选择使用把当前显示的convertView对应的position值保存在convertView中,然后把这个convertView对象传入OnClickListener中保存,所以代码演化到如下:
public View getView(int positon, View convertView, ViewGroup parent){
if(null == convertView){
convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
Button button = ABViewUtil.obtainView(convertView, R.id.item_btn);
button.setOnClickListener(new OnConvertViewClickListener(convertView, R.id.ab__id_adapter_item_position){
@Override
public void onClickCallBack(View registedView, int... positionIds){
Toast.makeText(context, "position: " + positionIds[0], Toast.LENGTH_SHORT).show();
}
});
}
convertView.setTag(R.id.ab__id_adapter_item_position, position);
}
就像上面第5行这样,Button绑定的是OnConvertViewClickListener,它是OnClickListener的一个实现类可以保存convertView到Listener中,到时候回调onClick方法的时候可以从保存的convertView中获取到当前显示的item的position(这个position是以tag的方式保存在convertView中的)。
当然,还需要做第12行这一步,它的目的是把当前显示的position保存到convertView中,提供给OnConvertViewClickListener获取当前的position。
这样就ok了,可以在onClickCallBack()方法中进行点击事件的处理了,每个button永远只有一个onClickListener。
注:使用OnConvertViewClickListener可以依赖AndroidBucket(https://github.com/wangjiegulu/AndroidBucket)项目
[Android]在Adapter的getView方法中绑定OnClickListener比较好的方法的更多相关文章
- CI中的控制器中要用model中的方法,是统一写在构造器方法中,还是在每一个方法中分别写
Q: CI中的控制器中要用model中的方法,是统一写在构造器方法中,还是在每一个方法中分别写 A: 建议统一写,CI框架会自动识别已经加载过的类,所以不用担心重复加载的问题 class C_User ...
- 为什么static方法中不可以调用非static方法
Java是面向对象的语言,所有的变量,方法都是针对对象而言的.一般来说,要调用一个方法,你需要new 这个方法的对象. 什么时候用static? 如果你想要: 对于一个类的所有对象共享一个变量或者是方 ...
- jQuery中绑定事件的几种方法
以click事件为例,jQuery中绑定事件有三种方法: (1)target.click(function(){}); (2)target.bind("click",functi ...
- BackgroundWorker的DoWork方法中发生异常无法传递到RunWorkedCompleted方法
在使用C#的BackgroundWorker时需要在UI界面上显示DoWork中发生的异常,但怎么调试都无法跳转到界面上,异常也不会传递到RunWorkerCompleted方法中(e.Error为空 ...
- hibernate方法中参数传入数组的查询方法
public List<T> getByIds(Long[] ids) { return getSession().createQuery(// "FROM User WHERE ...
- Android开发面试经——4.常见Android进阶笔试题(更新中...)
Android开发(29) 版权声明:本文为寻梦-finddreams原创文章,请关注:http://blog.csdn.net/finddreams 关注finddreams博客:http:/ ...
- .Net中的AOP系列之《方法执行前后——边界切面》
返回<.Net中的AOP>系列学习总目录 本篇目录 边界切面 PostSharp方法边界 方法边界 VS 方法拦截 ASP.NET HttpModule边界 真实案例--检查是否为移动端用 ...
- jQuery中绑定事件bind() on() live() one()的异同
jQuery中绑定事件的四种方法,他们可以同时绑定一个或多个事件 bind()-------------------------版本号小于3.0(在Jquery3.0中已经移除,相应unbind()也 ...
- Android总结篇系列:Activity中几个主要函数详解
Activity作为Android系统中四大基本组件之一,包含大量的与其他的各大组件.intent.widget以及系统各项服务等之间的交互的函数.在此,本文主要选取实际项目开发中常用的,但完全理解又 ...
随机推荐
- 寻找Fragment的替代品的尝试
自从Android在3.0推出Fragment之后,现在很多应用的设计都是建立在Fragment的基础上,像是多个tab切换这种需求,就可以使用Fragment,并且Fragment提供了一系列生命周 ...
- [AngularJS] AngularJS系列(2) 中级篇之路由
目录 原理 angular-route ui-router 事件 深度路由 原理 ng的route本质是监听hashchange事件. 在angular-route中 $rootScope.$on(' ...
- LeetCode - Triangle
题目: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjace ...
- BUG集锦
1.0 jQuery 序列化表单数据 serialize() 得到的是 ""; 表单元素没有name属性.(用的美工的页面,没注意这个细节.)
- 基于<MediaElement>的WPF视频播放器(可拖拽进度条播放)【1】
一.前言 前两天上峰要求做一个软件使用向导,使用WPF制作.这不,这两天从一张白纸开始学起,做一个播放演示视频的使用向导.以下是粗设计的原型代码: 二.效果图 三.代码 前台代码: < ...
- 介绍开源的.net通信框架NetworkComms框架 源码分析(十一)PacketBuilder
原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 许可是 ...
- ASP.NET MVC 网站开发总结(六)——简谈Json的序列化与反序列化
首先,先简单的谈一下什么是序列化与反序列化,序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通 ...
- Kinect V2 基础教程之彩色图像
本程序为自己所写,参考素材包括微软官方例子和外文资料,自己做了部分的优化.解释的如果有问题,恳请大家指正. 后台代码: using System.ComponentModel; using Syste ...
- 使用NISI制作.Net程序服务安装包
1.开篇之前先说一说NISI是什么. NSIS(Nullsoft Scriptable Install System)是一个开源的 Windows 系统下安装程序制作程序.它提供了安装.卸载.系统设置 ...
- 【Java每日一题】20161104
package Nov2016; public class Ques1104 { private String num; public void setNum(String num){ num = n ...