listView的多项删除功能实现

时间:2022-05-24 19:44:23

现在只要是android应用,基本上都会使用listView,而用到listView基本上又会用到数据库,用到数据库基本上都会对数据库进行增删改查,要进行增删改查基本上又要通过操作listView的item进行,那么如果数据量有很多条,但是又不想全部删完,也不想一条一条的删除,那么多项删除肯定是首选,下面进入正题:

首先明确一下要实现的具体的功能:

1,利用一个button往listView添加数据,数据存储采用数据库存储方式

2,数据添加完毕之后,长按listView的item,显示出checkBox,和底部的删除布局

3,选中某几条item时,进行删除,删除时提示选中了几条item,然后点击删除,则把数据从数据库删除

4,点击全选checkBox,选中所有item,再次点击,都不选中,手动把所有item全选中时,全选checkBox也会选中

5,若无数据时,提示没有选中任何条目

然后写一下大致的实现步骤:

1,实现界面布局

2,创建数据库和数据库的帮助类

3,采用List集合为listView填充数据

4,采用Map集合记录被选中的item中对应数据库id

5,删除

具体实现过程中的难点:

1,如何监听item长按时,显示相关界面

2,如何记录被选中的item的相关信息

3,如何一次性删除所有被选中的item

4,全选时,如何把所有item信息全部存储到map集合里

下面把一些关键点进行说明,在文章结束时会附上demo源码,源码的注释非常详细,基本上每一行代码都做了注释,大家可以下载仔细研究,下载需要2点积分

1,关于数据库的创建以及数据库的帮助类,还有为listView设置adapter就不细说了,大家可以去看源码.

第一步先说一下如何监听item长按事件进行相关界面的显示.

监听item长按事件,肯定要实现listView的onItemLongClick监听,在此之前声明一个boolean类型的成员变量isLongClick=false,当监听到长按事件时,isLongClick=true,并

重新刷新listView,如下代码:

 @Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
//如果是长按,则把isLongClick置为true,并把相关布局都显示出来,然后再次刷新listView
isLongClick = true;
ll.setVisibility(View.VISIBLE);
mList = impl.queryAll();
listView.setAdapter(new MyAdapter());
return false;
}
和BaseAdapter里的部分代码如下:

            //如果是长按item,则显示checkBox
if (isLongClick) {
holder.delete_cb.setVisibility(View.VISIBLE);
}
//否则,隐藏checkBox
else {
holder.delete_cb.setVisibility(View.INVISIBLE);
}

2,如何保存被选中的item的相关信息
这里采用Map集合进行相关数据的存储,不要使用List集合,因为用户会有这样一个需求,比如选中了一些item 的checkBox,然后又取消选中某些checkBox,这样的话,我们需要把之前存储的item信息从集合里移除掉,如果采用List集合进行存储的话,在移除方面相当困难,你找不到一个合适的方法能准确的把那些个item记录移除掉,搞不好还会导致数组下标越界异常,所以我们需要一个能精确记录数据的集合,能确保在用户反复无常的选中与取消选中过程中,精准的添加与删除相关数据,而Map集合就具有这个优势,添加数据时,Map集合以键值对的形式进行添加,而移除数据时,Map集合根据键来移除相应的值,这个键也不能随意设置,需要以listView的position为键进行存储,具体详细的解析,代码里有详细的注释

代码如下:

添加时:

 //每选中一个checkBox,就把该checkBox所在item的id存储到map集合中,用来删除
map.put(position, mList.get(position).getId());

移除时:

 //若用户选中checkBox之后又取消选中,则把对应的存储信息移除,根据position来移除对应的信息
//这也是为什么采用map集合,而不采用list集合的原因(list集合删除对应数据没有map集合简单)
map.remove(position);
3,如何控制全选checkBox的相关操作:

全选checkBox的作用就是全部选中item与全部不选中item,我们需要定义一个boolean类型的成员变量isSelectedAll=false,当全选时,isSelectedAll=true,然后再次刷新ListView,

这时要注意,我们不能从adapter里获取数据添加到map集合中,不然会有一个bug,即所有item都被选中了,但是item的信息只有10条左右保存到了map集合,其他item信息并没有被保存,而这种情况发生在listView数据较多时(几十条以上),现在解释一下这个bug发生的原因:现在大部分手机屏幕都差不多,一个屏幕一般能容纳10条左右的数据,而为listView设置适配器时,为了listView的性能考虑,一般都会使用ViewHolder为listView进行优化,而ViewHolder的作用就是减少执行加载item布局的次数,复用之前的item布局控件,从而减少listView的性能消耗,也就优化了listView的性能,但这也就导致了当数据较多时刷新listView,只会刷新当前屏幕的数据,其他数据不会刷新,所以就导致了这个bug,要避免这个bug,也很简单,只要换其他方式进行item数据的加载就可避免,我采用就是当全选时,遍历list集合,把list集合里的数据都添加到map集合里,然后再进行删除,其实还有一个方法可以避免该bug,就是在删除时,直接把list集合传递过去,但是这样做的话,会增加很多代码量,下面是我的解决方式:

        //如果selectAll_cb被选中,则把isSelectAll置为true,并再次刷新listView
//这里要注意,因为一个手机屏幕一般容纳10几条内容,如果全选,其实只选中了这10几条item,
//后面的虽然也被选中了,但是相应的item数据并没有添加到map集合里,
//所以,要想删除全部数据,则要遍历mList集合,把所有数据存储到map集合里
if (isChecked) {
isSelectAll = true;
for (int i = 0; i < mList.size(); i++) {
map.put(i, mList.get(i).getId());
}
mList = impl.queryAll();
listView.setAdapter(new MyAdapter());
}
4,删除选中的item,

删除item,根本上还是删除数据库的数据,而删除数据库数据时,因为数据库id是唯一的,所以可以很据其id来进行删除,之前也说了,把数据库的id存储到map集合里,所以在删除时,

把map集合传递过去,然后遍历map,遍历一条,删除一条,这样就实现了多项删除,如下代码:

 /**
* 多项删除,根据map集合来删除,该map集合存储每个要删除的item的id
*
* @param map
*/
@Override
public void deleteOfMulti( Map<Integer, Integer> map) {
SQLiteDatabase database = helper.getWritableDatabase();
//利用collection集合存储map里的值
Collection<Integer> values = map.values();
for (int id : values) {
database.delete("text", "id=?", new String[]{id + ""});
}
database.close();
}
这里也会有一个性能问题,就是当listView里数据有很多很多条时,删除时会很耗时间,这里提供两个解决思路,一个就是当数据很多很多时,先把这些item隐藏,因为隐藏用时很短,给用户的感觉就是数据一下就删除完了,而实际上,数据库的删除还在继续.另一个就是,啥也不管,只要删除,就用progressBar进行过渡,并监测map集合的长度,开始删除时显示,当map集合长度为0时,隐藏progressBar即可.

OK,一些核心点基本说完了,还有一些细节,必须要注意的在demo里注释的很详细,大家可以下载看一下,实现多项删除功能的方式有很多,我这只是其中一种.

下面上效果图(一直想上传动态图,比较直观,但不知道如何上传,知道的朋友,不妨留个言说一下):

listView的多项删除功能实现listView的多项删除功能实现listView的多项删除功能实现listView的多项删除功能实现

源码下载地址:http://download.csdn.net/detail/qiang_xi/9292809

如果这篇文章对你有帮助,不妨点个赞或评论一下.