Android AOS 4.x和ListView出现问题-在ListView滚动时更改数据

Android AOS 4.x和ListView出现问题-在ListView滚动时更改数据,android,listview,crash,scroll,android-4.0-ice-cream-sandwich,Android,Listview,Crash,Scroll,Android 4.0 Ice Cream Sandwich,我在Android OS v4.x上遇到了一个问题,特别是4.0.3,在滚动时更改ListView的数据-发生了一个崩溃,说我试图更改的数据不是来自主UI线程,这是不正确的: E/AndroidRuntime(2453): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the c

我在Android OS v4.x上遇到了一个问题,特别是4.0.3,在滚动时更改ListView的数据-发生了一个崩溃,说我试图更改的数据不是来自主UI线程,这是不正确的:

    E/AndroidRuntime(2453): 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(16908298, class android.widget.ListView) with Adapter
(class mypackage.activity.MyListViewActivity$ListViewAdapter)]
ListView的UI由两部分组成——最大的部分是ListView,底部有一个特殊的控件,可以触发数据更改,并且该控件始终可见。所以用户可以启动ListView滚动,当它滚动时,用户可以使用触发ListView数据更改的控件,这会导致崩溃。当然,数据更改发生在mainUI线程上,我使用notifyDataSetChanged:

loadData方法只是用其他数据填充相应的ArrayList:

    void loadData() {
        List<DataHolder> tempDataList = DataRetriever.getData(currentMonth);
        dataList.clear();
        dataList.addAll(tempDataList);
    }

所以这里没有什么特别的。AOS 2.3.5不会发生崩溃。在AOS 4上获得相同崩溃的另一种方法是在数据更改后点击屏幕,ListView滚动到顶部。出了什么问题以及如何避免此错误?

到目前为止,我找到的唯一解决方法是在更改数据之前停止列表滚动:

// before changing the data of ListView's adapter
if (listView!=null){
    MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0);
    listView.dispatchTouchEvent(me);
    me.recycle();
}
// now its safe to change data and call notifyDatasetChanged()
// before changing the data of ListView's adapter
if (listView!=null){
    MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0);
    listView.dispatchTouchEvent(me);
    me.recycle();
}
// now its safe to change data and call notifyDatasetChanged()