android 修改listview中adapter数据时抛出异常java.lang.IllegalStateException: The content of the adapter has cha...

近日在做项目时遇到非必现crush,具体异常信息为:

// Short Msg: java.lang.IllegalStateException

 

// Long Msg: 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. [in ListView(2131624004, class android.widget.ListView) with Adapter(class com.baidu.smartcalendar.widget.cx)]

 

// Build Label: Coolpad/pxa1088dkb_def/8750:4.2.1/JOP40D/4.2.063.P1.131218.8750:user/release-keys

 

// Build Changelist: 4.2.016.P1.8750

 

// Build Time: 1387361194000

 

// 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. [in ListView(2131624004, class android.widget.ListView) with Adapter(class com.baidu.smartcalendar.widget.cx)]

 

// at android.widget.ListView.layoutChildren(ListView.java:1559)

 

// at android.widget.AbsListView.onTouchModeChanged(AbsListView.java:3313)

 

// at android.view.ViewTreeObserver.dispatchOnTouchModeChanged(ViewTreeObserver.java:712)

 

// at android.view.ViewRootImpl.ensureTouchModeLocally(ViewRootImpl.java:3078)

 

// at android.view.ViewRootImpl.ensureTouchMode(ViewRootImpl.java:3062)

 

// at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3206)

 

// at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3169)

 

// at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4300)

 

// at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4279)

 

// at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4371)

 

// at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:179)

 

// at android.os.MessageQueue.nativePollOnce(Native Method)

 

// at android.os.MessageQueue.next(MessageQueue.java:125)

 

// at android.os.Looper.loop(Looper.java:124)

 

// at android.app.ActivityThread.main(ActivityThread.java:5078)

 

// at java.lang.reflect.Method.invokeNative(Native Method)

 

// at java.lang.reflect.Method.invoke(Method.java:511)

 

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

 

// at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:623)

 

// at dalvik.system.NativeStart.main(Native Method)

 

异常的描述是不要在其他线程中修改listview的adapter数据而在ui线程中进行刷新notifyDataSetChanged()。我们一般为adapter添加数据时常常使用activity类内部的全局变量,这时在外部或其他线程中更新数据时,如果不及时刷新listview,就会抛出上述异常。于是我去掉线程,直接在ui线程中更新数据,发现问题依然存在。

仔细查看代码,我的代码是这样的:

private void prepareData(Calendar c) {
        mTodayList = new ArrayList();
        mFutureList = new ArrayList();
        mList = new ArrayList();
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        ArrayList list = SmartCalendarDB.getInstance(getActivity())
                .getBirthdayLatest2(mCalendar.getTimeInMillis(),
                        cal.getTimeInMillis() != mCalendar.getTimeInMillis());
        if(list != null && list.size() > 0) {
            int month = mCalendar.get(Calendar.MONTH) + 1;
            int day = mCalendar.get(Calendar.DAY_OF_MONTH);
            for(SCEvent e : list) {
                if(e.getmBirthdayMonth() == month && e.getmBirthdayDay() == day) {
                    mTodayList.add(e);
                } else {
                    mFutureList.add(e);
                }
            }
            if(mTodayList != null && mTodayList.size() > 0) {
                Collections.sort(mTodayList, new TimeComparator());
                for(SCEvent e : mTodayList) {
                    mList.add(e);
                }
                mList.add(null);
            }
            if(mFutureList != null && mFutureList.size() > 0) {
                if(mTodayList == null || mTodayList.size() <= 0) {
                    mList.add(null);
                }
                Collections.sort(mFutureList, new AdvanceComparator());
                boolean add = mList != null && mList.size() > 0;
                for(SCEvent e : mFutureList) {
                    mList.add(e);
                }
                if(!add) {
                    mList.add(null);
                }
            }
        }
        if(mList != null && mList.size() > 0) {
            mListView.setVisibility(View.VISIBLE);
            mEmptyLayout.setVisibility(View.GONE);
            mAdapter.notifyDataSetChanged();
        } else {
            mListView.setVisibility(View.GONE);
            mEmptyLayout.setVisibility(View.VISIBLE);
        }
    }

我的adapter数据是保存在mlist中,而在代码中不断的改变了mlist内部的数据,而只在最后调用了一次mAdapter.notifyDataSetChanged(),导致listview没有及时刷新而抛出异常。

所以结论在使用listview时,及时不在非ui线程中更新adapter数据,也最好将数据直接定义在adapter类内部或在改变数据时要及时刷新listview,否则会抛出上述异常。

转载于:https://www.cnblogs.com/gccBlog/p/3747365.html

你可能感兴趣的:(android 修改listview中adapter数据时抛出异常java.lang.IllegalStateException: The content of the adapter has cha...)