1. 程式人生 > >非同步載入Listview The content of the adapter has changed but ListView did not receive a notification

非同步載入Listview The content of the adapter has changed but ListView did not receive a notification

錯誤

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

原因

在Android開發過程中,使用了大量的ListView,發現這個錯誤偶爾會出現。特別是做壓力測試的時候,不停的點選重新整理,更容易出現這個錯誤。程式碼中已經使用了Adapter的notifyDataSetChanged()方法通知UI更新了,但是還是會出現這個錯誤。究其根本原因,還是執行緒之間同步的問題。比如,執行緒1更新了Adapter中的內容,卻還沒有來得及通知內容已經更新,就又有執行緒2更新了Adapter中的內容,這個時候如果執行緒1再通知內容更新,就會出現上述異常了

解決方法

ListView的滾動有三種狀態
第一是靜止狀態,SCROLL_STATE_IDLE
第二是手指滾動狀態,SCROLL_STATE_TOUCH_SCROLL
第三是手指不動了,但是螢幕還在滾動狀態。SCROLL_STATE_FLING
在靜止狀態 進行adapter 更新即可 示例程式碼如下:
class ListOnScrollListener implements AbsListView.OnScrollListener {

        private int visibleLastIndex;
        private LegworkAdapter adapter;
        private RTPullListView listView;
        private View footer;

        public ListOnScrollListener(LegworkAdapter adapter, RTPullListView listView, View footer) {
            this.adapter = adapter;
            this.listView = listView;
            this.footer = footer;

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                             int visibleItemCount, int totalItemCount) {
            visibleLastIndex = firstVisibleItem + visibleItemCount - 1;
			/* 如果滾動到最後一條 */
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            if (adapter != null) {
                int itemsLastIndex = adapter.getCount(); // 資料集最後一項的索引
                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE && visibleLastIndex == itemsLastIndex) {
                    //靜止狀態在進行adapter更新 否則異常退出
                    adapter.notifyDataSetChanged();
                    if (page < totalpage) {
                        listView.addFooterView(footer);
                        page = page + 1;
                        flag = true;
                        SharedPreferenceUtils sharedPreferenceUtils = new SharedPreferenceUtils(LegworkActivity.this);
                        String subUrl = sharedPreferenceUtils.getString(SharedPreferEnum.SUB_URL.name());
                        int empId = sharedPreferenceUtils.getInt(SharedPreferEnum.EMP_ID.name());
                        new Task().execute(subUrl, String.valueOf(empId), String.valueOf(page), String.valueOf(Constant.PAGE_SIZE));
                    }
                }
            }
        }
    }