ListView结合getView来显示数据的时候,可能每一个listItem都需要后台进行大量的耗时处理,比如从网络下载,或者计算得出结果等等。这时候如果用户滚动ListView就会得到不好的用户体验,会很卡。
可以这样解决这个问题:
当用户滚动屏幕的时候,监听listview滚动onScroll()和停止滚动的事件onScrollStateChanged()。
每次滚动的时候触发onScroll(),在onScroll()中获得firstVisibleItem和visibleItemCount。保存起来。
当用户停止滚动的时候,触发onScrollStateChanged(),这时候将获得的firstVisibleItem和visibleItemCount传递给自定义的一个接口方法scrollTo()。
在scrollTo()中开启一个AsyncTask线程。通过这个线程来实现后台数据的加载
Activity:
class LvOfCallLogsScrollListener implements OnScrollListener { private int firstVisibleItem; private int visibleItemCount; public void onScrollStateChanged(AbsListView view, int scrollState) { System.out.println("---------onScrollStateChanged---------" + scrollState + " ==" + OnScrollListener.SCROLL_STATE_IDLE + "firstVisibleItem" + firstVisibleItem + "visibleItemCount:" + visibleItemCount); if (popWindowOfKeyboard.isShowing()) { popWindowOfKeyboard.dismiss(); sendBroadcastToMain(KEYBOARD_CLOSED); } if (myPopupWindowOfCallLogSort.isShowing()) { myPopupWindowOfCallLogSort.dismiss(); } if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) if (view.getAdapter() instanceof GenerateItemView) { ((GenerateItemView) view.getAdapter()).scrollTo( firstVisibleItem, visibleItemCount); } } public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // System.out.println("---------onScroll---------"); this.firstVisibleItem = firstVisibleItem; this.visibleItemCount = visibleItemCount; if(firstVisibleItem==0) { if (view.getAdapter() instanceof GenerateItemView) { ((GenerateItemView) view.getAdapter()).scrollTo( firstVisibleItem, visibleItemCount); } } } }
BaseAdapter:
/** * * @param firsP * @param lasp */ public void scrollTo(int firsP,int lasp) { loadRunnable=new LoadRunnable(firsP,lasp); loadRunnable.execute(null); } private class LoadRunnable extends AsyncTask { private int first; private int visible; public LoadRunnable(int firsP,int visible) { first=firsP; this.visible=visible; } @Override protected void onPostExecute(Object result) { //..... notifyDataSetChanged(); } @Override protected Object doInBackground(Object... params) { //.....耗时操作 for(int i=0;i<visible;i++) listOfPersonList.get(i+first).get(0).setTelLocation("fuzhou"); return null; } };
但是这样做有一个不好的地方,当用户一直滚动的时候,会出现明显的加载数据延时。因为没有把无效滚动的消息忽略掉。