关于listview 更新数据后没有更新界面

Adapter通常的写法都是用一个成员变量Data持有着对数据的引用,然后在active中对data数据进行修改即可更新界面显示。

但是有些情况下可能无法更新。

网上有很多,具体分为(引用别人的分析):

 List mSongVOs = getSongs(A);//数据A

SongAdapter mSongAdapter = new SongAdapter(getApplicationContext(), mSongVOs);//用数据初始化适配器

lvMusicList.setAdapter(mSongAdapter);//为ListView绑定适配器

 

//情况1.

可以刷新Listview数据

mSongVOs.remove(x);

mSongAdapter.notifyDataSetChanged();

 

//情况2.不刷新

mSongVOs=getSongs(B);//数据B

mSongAdapter.notifyDataSetChanged();

 

//情况3.可以刷新

mSongVOs.clear();

mSongVOs.addAll(helper.getAudios());

mSongAdapter.notifyDataSetChanged();

之后ListView的刷新都是通过Adapter.getItem()等方法进行更新,而这些方法访问的数据时这个mData指向的数据。如果这个数据不变,那么notifyDataSetChanged自然不会刷新。

在情况1、3中,局部变量mSongVOs和SongAdapter的成员变量mData指向的是同一块内存地址,即数据A,因此mSongVOs修改A后,notifyDataSetChanged通过mData再访问A时发现数据变了,所以就更新了ListView。
在情况2中,局部变量mSongVOs通过getSong(B)获取新数据B,实际是mSongVOs指向了内存中另外一块地址B,而此时mData指向的仍然是A。因此notifyDataSetChanged观察到A始终没有变化,因此不刷新。

所以,情况2,并不是Adapter“数据变了却不刷新”,而是“数据根本没变”。
而网上说重新对adapter绑定即可刷新,实际上就是重新绑定了成员变量mData,因此可以刷新。

情况2、3的业务逻辑是换了一整批数据,编程上情况2似乎是很直观和合理的,但是得注意了,得用第三种写法。

 

还有一种情况:

最终原因就是数据引用导致:adapter里面针对A进行多层引用(adapter基类中又有新数据生产),即时你在前台页面更新了A,然后在在adapter的处理中数据还是没变。怎么办?

那就在基类中写一个更新方法,来触发更新。

比如:

    /**
     * 更新在线状态方法
     * @param user
     * @param flag
     */
    public void UpdateChangePostion(String user,boolean flag)
    {

       //nodes就是传递进来的数据副本,下面的方法直接对Nodes中的数据进行修改来达到更新重绘

       //这种情况,你要注意你的数据库与内存的联系,各自处理。
        for(Node node:Nodes)
        {
            if(node.getUserName().equals(user))
            {
                node.setStatus(flag);
            }    
        }
        notifyDataSetChanged();
    }

具体的方法可以自己写,这个只是思路。

转载于:https://www.cnblogs.com/Fle-x/articles/7000402.html

你可能感兴趣的:(关于listview 更新数据后没有更新界面)