美文网首页
关于Adapter的The content of the ada

关于Adapter的The content of the ada

作者: KUN叔 | 来源:发表于2017-06-19 14:57 被阅读91次

    1、问题描述
    在使用Listview给Adapter填充数据的时候,在Mi max手机上下拉刷新的时候崩了,当时只有这个手机遇到这个问题,其他手机都OK,log大概如下;

    java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.

    2、复现场景
    使用ListView和Adapter实现动态增删数据列表功能,初始化数据分为两部分:本地和网络。所以在Adapter的数据初始化的时候,先讲本地数据添加到了容器内。同时发起网络请求,等加载完毕后追加到容器内。
    问题出现在:当网络请求完毕后追加数据的时候,抛出上述异常。

    3、原因分析
    Exception解读:
    Adapter的数据内容已经改变,但是ListView却未接收到通知。要确保不在后台线程中修改Adapter的数据内容,而要在UI Thread中修改。确保Adapter的数据内容改变时一定要调用notifyDataSetChanged()方法。

    当ListView缓存的数据Count和ListView中Adapter.getCount()不等时,会抛出该异常。

    结合开头的异常解读,可以断定肯定是Adapter数据动态更新的问题。仔细检查了自己的代码:
    -我的情况
    下拉的时候会去请求数据,在网络线程(非UI线程)然后判断pageNum是否等于1,如果等于1的话,list.clear(),然后把这个请求到的数据添加到list里面,但是这个处理是在runOnUiThread中,我分析的原因是,clear操作在子线程还未处理的时候,先执行了list.add(),造成越界。后来把处理都移到runOnUiThread中,如下:

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (pageNum == 1) {
                        infoList.clear();
                    }
                    infoList.addAll(reList);
                    adapter.setData(infoList);
                    adapter.notifyDataSetChanged();
                }
            });
    

    -其他情况
    当网络请求完毕后,直接在网络线程(非UI线程)里调用了在Adapter中新增的自定义方法addData(List)更新数据,而addData(List)方法内更新换完数据后,通过Handler发送Message的策略调用Adapter的notifyDataSetChanged()方法通知更新。

    这么一来,并不能保证Adapter的数据更新时,立马调用notifyDataSetChanged()通知ListView,这两个线程之间的时间差引起的数据不同步,导致ListView的layoutChildren()中访问Adapter的getCount()方法时,Adapter内已经是最新数据源,而ListView内的缓存数据Count仍是旧数据的Count,该问题最终原因终于浮出水面。

    归根结底都是一个原因。

    4、解决方案
    在本例中,解决方案是:把addData(List)方法内更新数据的代码挪出来,和notifyDataSetChanged()方法一同放在Handler里,保证数据更新时及时通知ListView。

    为了尽量避免该问题,以后编程尽量从如下几个方面检查自己的代码:

    确保Adapter的数据更新后一定要调用notifyDataSetChanged()方法通知ListView
    数据更新和notifyDataSetChanged()放在UI线程内,且必须同步顺序执行,不可异步
    仔细检查确认getCount()方法返回值是否正确

    相关文章

      网友评论

          本文标题:关于Adapter的The content of the ada

          本文链接:https://www.haomeiwen.com/subject/irigqxtx.html