Android中适配器的notifyDataSetChanged()为何有时不刷新
admin
2023-07-26 00:20:06
0
        学过Android开发的人都知道,ListView控件在开发中经常遇到,并且ListView通常结合Adapter适配器来进行数据显示和数据更新操作。姑且假设数据存储在名为dataList的成员变量中。数据操作无非是增加数据、删除数据这两种主要的操作,而当数据有所变化时,为了及时向用户提供更新后的数据,我们知道需要在数据更新后调用适配器的notifyDataSetChanged()方法,来显示更新后的数据。殊不知,该方法并非百试不爽,在此我们便来讨论下具体的原因,其实本质是关注内存的分配情况。
        先来看几段代码。
        代码段1(某Activity中):
private List> dataList;
private ListView listView;
private ListAdapter adapter;

listView = findViewById(R.id.mancard);
adapter = new ListAdapter(this, dataList);
listView.setAdapter(adapter);
        上述代码是把Adapter适配器和ListView控件进行绑定。
        代码段2(ListAdapter中的部分代码):

public class ListAdapter extends BaseAdapter{
private Context context;
private List list;

ListAdapter(Context context, List list){
        this.context = context;
        this.list = list;
}
@Override
public Object getItem(int position) {
        return list.get(position);
}
        上述代码是通过上下文环境和数据列表来构造适配器,并且重写其getItem()方法。在此需要明白的是list成员变量是适配器中的私有变量,getItem()方法是当数据显示在ListView时会回调的方法,或者说当显示数据或数据发生改变重写加载数据时会回调这个方法(当然还会调用getView()方法,此时不再赘述)。
        代码段3~6模拟数据改变:
        代码段3:

dataList.remove(1);
adapter.notifyDataSetChanged();
代码段4:
Map vivian = new HashMap();
vivian.put("sex", "girl");
vivian.put("nick", "vivian");
vivian.put("content", "阳光魅力大方无极限");
dataList.add(vivian);
adapter.notifyDataSetChanged();
代码段5:
dataList = getData();
adapter.notifyDataSetChanged();

private List getData(){
        List data = new ArrayList();
        Map vivian = new HashMap();
        vivian.put("sex", "girl");
        vivian.put("nick", "vivian");
        vivian.put("content", "阳光魅力大方无极限");
        data.add(vivian);

        Map Mryang = new HashMap();
        Mryang.put("sex", "boy");
        Mryang.put("nick", "杨阳洋");
        Mryang.put("content", "成熟稳重高富帅");
        data.add(Mryang);

        return data;

}

        代码段6:

dataList.clear();
dataList.addAll(getData());
adapter.notifyDataSetChanged();

getData()方法同代码段5(略)
以上几种情况模拟了常用的更新数据的方法,在这几种情况种代码段5不能实现数据的更新操作,代码段3、4、6可以实现数据更新操作。为什么代码段3、4、6可以更新,原因大家都明白,是因为数据发生了变化,因此当调用adapter.notifyDataSetChanged()方法时就会把更新后的数据显示出来。
代码段5的数据也发生了变化,为什么不能实现数据更新呢?
当构造Adapter适配器,数据列表dataList传递过去时,是把dataList指向的地址副本作为参数传递给了adapter中的list成员变量了,因此dataList指向的内存区域和adapter中list指向的内存区域是同一块内存区域,代码段3和代码段4对数据的添加、删除操作是在当前区域内进行的,dataList中数据的变化直接影响了adapter中list的数据的变化,因此adapter中的list能够敏感的发现数据发生变化。

Android中适配器的notifyDataSetChanged()为何有时不刷新

                                            代码段3、4简易模型
        代码段5中,对dataList的内存指向做了修改,但是该指向并没有通知到adapter中的list,也就是说list指向没有发生变化,还是指向原来修改前的内存区域,因此dataList的改变并不能引起list的改变,本质上来说list没有发现数据有变化,所以当调用adapter.notifyDataSetChanged()方法时,数据没有更新。而在代码段6中,首先移除dataList中的数据,那么adapter中的list自然能够及时发现数据发生了变化,从而重新从dataList中得到改变后的数据信息,因此当调用adapter.notifyDataSetChanged()方法时能够发生数据的更新。

Android中适配器的notifyDataSetChanged()为何有时不刷新

                代码段5简易模型

Android中适配器的notifyDataSetChanged()为何有时不刷新

        代码段6简易模型
        因此当我们想要更换ListView中的所有数据时,应该采用代码段6的方式,先将数据移除,再重新添加数据或更换新的内存区域指向。

相关内容

热门资讯

国安部警示:近300亿份游戏环... 近期,有外媒披露,某知名AR手游旗下人工智能公司获取了游戏用户上传的近300亿份环境扫描数据,可能将...
中方在联合国人权理事会妇女权利... △联合国日内瓦办事处(资料图)联合国人权理事会第62届会议妇女权利问题研讨会近日在瑞士日内瓦召开,中...
河水水温温度过高,法国瑞士先后... 热浪侵袭下,欧洲多国基础设施的稳定运转面临严峻挑战。近日,法国和瑞士先后宣布,暂时关闭各两座核反应堆...
演员没戏,回家种地? 董子健和刘昊然在舞台上直白地向导演们“求”工作机会那天,转行菜农的短剧演员张小磊在大棚里摘了三百斤彩...
四川宜宾发生5.5级地震,距震... 据中国地震台网正式测定:6月29日0时12分,在四川宜宾市高县(北纬28.50度,东经104.69度...
原创 为... 2024年10月30日凌晨,酒泉卫星发射中心,长征二号F运载火箭托举着神舟十九号冲天而起。火光划破戈...
神舟二十三号乘组在轨满月 解锁... 首先来关注中国空间站的消息。目前,神舟二十三号乘组航天员朱杨柱、张志远、黎家盈在轨已满一个月,在稳步...
美官员:美伊计划于30日在卡塔... △卡塔尔首都多哈(资料图)总台记者当地时间6月28日获悉,一位美国高级官员透露,美伊双方已同意停止相...
普京:建议乌俄双方均停止打击对... 当地时间6月28日,俄罗斯总统普京向媒体表示,俄方建议俄乌双方均停止攻击对方领土的纵深目标,否则俄方...
伊朗缺席28日技术性谈判 △伊朗首都德黑兰(资料图)总台记者当地时间6月28日获悉,一位伊朗官员称,伊朗未参加原定于当天举行的...