优化listview 有哪些方法

 我来答
就烦条0o
2016-12-12 · 知道合伙人软件行家
就烦条0o
知道合伙人软件行家
采纳数:33315 获赞数:46492
从事多年系统运维,喜欢编写各种小程序和脚本。

向TA提问 私信TA
展开全部
有一个小细节,很多开发人员都没有注意过

比如你的Item中有三个按钮,你要为三个按钮分别定义点击事件,如何定义?

也许你会在getView中这样做

button1.setOnclickListener(new View.OnClickListener() {
@override
public void onClick(View v) {
//balabalabala...
}
});

button2.setOnclickListener(new View.OnClickListener() {
@override
public void onClick(View v) {
//balabalabala...
}
});

button3.setOnclickListener(new View.OnClickListener() {
@override
public void onClick(View v) {
//balabalabala...
}
});

如果你每屏显示7个Item,你一共创建了21个listener对象在内存中,如果View回收不畅,会更多,这样,在滚动的时候频繁GC 就会导致卡顿(这里描述有误,请看7月25日更新)

如果你在Adapter初始化的时候创建一个Listener

public MyAdapter () {
myListener = new View.OnClickListener() {
@override
public void onClick(View v) {
v.getTag()
v.getId()
//balabalabala...
}
});
}

通过传入的View v这个参数判断是哪一个button被点击,这样,无论View如何创建,你只创建了1个Listener对象

这只是一个小细节,优化的方式要综合使用,才会事半功倍

------------------7月24日更-----------------

v.getTag() 这个tag本不是用来存数据的,通俗点讲它和view 的Id是同一个东西,只不过tag的类型是Object。实际上在tag中存储数据是不符合规范的方式

但其实View类有两种tag,

setTag(Object tag) 方法将tag保存在一个成员变量中,findViewWithTag正是遍历此tag

setTag(int key, Object tag) 方法是最终是调用View类中的setKeyedTag(int key, Object tag)
这是一个私有方法

他是用 SparseArray 实现的,我们可以把需要的东西存到这里面(其实观察源码可以发现,系统很多时候都是这样做的)

这里要注意一点,参数key必须是唯一的,那么我们可以这样做
那么需要先在res/values/strings.xml中添加

<resources>
<item type="id" name="tag_first"></item>
<item type="id" name="tag_second"></item>
</resources>

使用的时候写成

view.setTag(R.id.tag_first, obj1);
view.setTag(R.id.tag_second, obj2);

-------------------------关于如何绑定数据的问题-----------------

有人问,如果这样写,所有button只能通过id区分逻辑,无法传入每个item的数据

我们可以将数据通过view 的tag带进来

public View getView(.....) {
....
v.setTag(key, getItem(position));
....
}

然后在listener中通过v.getTag()将数据取出

-----------------------7月25日update-------------------

这里我有一个失误

如果listener里面的逻辑与当前的item有关,那么其实并不只是创建了21个listener对象

public void getView (View convertView ,final int position ....) {
if (convertView == null) {
View v = LayoutInflater.from(mContext).inflate(...);
v.setOnclickListener(new View.OnClickListener () {
@override
public void onClick(View v) {
getItem(position);
}
});
} else {

}
}

你看下,如果绑定数据在convertView为空的情况下确实只创建了有限个listener,
但是在这种情况下绑定上的数据只有View创建时的7个,之后不为空的情况下没有更换listener导致重用的view数据是新的,listener里面的position依然是过去创建view时的7个之一,不会变化(注意参数上的final)

若在else里面再重新setListener,view是有重用,listener被换成新的,并与新的position绑定,老的listener就会变成一个废对象,等待gc回收,随着list滚动,越来越多
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式