The content of the adapter has changed but ListView did not receive

来源:互联网 发布:淘宝网买鞋子 编辑:程序博客网 时间:2024/06/10 01:42

主要原因就是你List数据变化了 但是没有通知adapter去notify

在修改bug的过程中,看到一个bug;里面的异常日志是:

java.lang.IllegalStateException:The content of the adapter has changed but ListView did not receive anotification. Make sure the content of your adapter is not modified from abackground thread, but only from the UI thread. Make sure your adapter callsnotifyDataSetChanged() when its content changes. [in ListView(2131296454, classcom.android.contacts.widget.AutoScrollListView) with Adapter(classcom.android.contacts.group.GroupBrowseListAdapter)]

atandroid.widget.ListView.layoutChildren(ListView.java:1555)

atcom.android.contacts.widget.AutoScrollListView.layoutChildren(AutoScrollListView.java:74)

atandroid.widget.ListView.setSelectionInt(ListView.java:1987)

atandroid.widget.AbsListView.resurrectSelection(AbsListView.java:5512)

atandroid.widget.AbsListView.onWindowFocusChanged(AbsListView.java:2858)

atandroid.view.View.dispatchWindowFocusChanged(View.java:7900)

atandroid.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:968)

atandroid.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)

atandroid.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)

at android.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)

atandroid.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)

atandroid.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)

atandroid.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)

atandroid.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)

atandroid.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3149)

atandroid.os.Handler.dispatchMessage(Handler.java:102)

at android.os.Looper.loop(Looper.java:136)

atandroid.app.ActivityThread.main(ActivityThread.java:5120)

atjava.lang.reflect.Method.invokeNative(Native Method)

atjava.lang.reflect.Method.invoke(Method.java:515)

at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:818)

atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:634)

atdalvik.system.NativeStart.main(Native Method)

简单来看的话,是一个IllegalStateException,从ListView 1555行抛出来的。

// Handle the empty set by removing all views that are visible// and calling it a dayif (mItemCount == 0) {      resetList();      invokeOnItemScrollListener();      return; } else if (mItemCount != mAdapter.getCount()) {      throw new 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. [in ListView(" + getId() + ", " + getClass()      + ") with Adapter(" + mAdapter.getClass() + ")]"); }
找到这行代码


也就是说当mItemCount != mAdapter.getCount()的时候会抛出这个异常。那么思考两个问题

1. mItemCount什么时候赋值?
2. mAdapter.getCount()又是什么呢?

先分析第2点,mAdapter.getCount(),因为这相对比较简单,大家也比较熟悉。没错,就是我们自定义Adapter的时候,重写的getCount()的方法。

类似于这种写法

public class GroupBrowseListAdapter extends BaseAdapter {         ...         Private List<String> mdata;         public int getCount() {        return mdata.size();}...}
一般返回就是要显示集合(list,cursor,数组)之类的大小,也就是你listview的Item总数目



那么来分析第1点,mItemCount 是什么赋值的呢?

首先,找到它定义的地方

文件路径:

frameworks\base\core\java\android\widget\AdapterView.java
代码:
/**     * The number of items in the current adapter.     */@ViewDebug.ExportedProperty(category = "list")int mItemCount;
赋值的地方

1.        ListView.setAdapter

public void setAdapter(ListAdapter adapter) {...if (mAdapter != null) {mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();mOldItemCount = mItemCount;mItemCount = mAdapter.getCount();...}...}
2.        frameworks\base\core\java\android\widget\AdapterView.java
class AdapterDataSetObserver extends DataSetObserver {private Parcelable mInstanceState = null;<a href="http://home.51cto.com/index.php?s=/space/5017954" target="_blank">@Override</a>public void onChanged() {mDataChanged = true;mOldItemCount = mItemCount;mItemCount = getAdapter().getCount();....}
上面是两处给mItemCount赋值的地方

第1个是给ListView设置adapter的时候,第2个调用adapter.
notifyDataSetChanged()的时候调用



那么解决这个问题就很简单了,就是你的数据集变化的时候(这个时候getCount()返回值就会变化),调用adapter. notifyDataSetChanged()通知adapter去更新mItemCount。

0 0