Android控件_ListView優化[分批加載]


對ListView的優化一直都是個讓人頭疼的問題....

        在ListView中普遍的分批加載優化無非是給listView設置滑動監聽,實現監聽接口,在 onScrollStateChanged() 方法中判斷滑動的狀態,當判斷滑到最底部(靜止狀態)的時候去執行分批加載的方法,貼簡單代碼:

myList.setOnScrollListener(new OnScrollListener(){
				
				@Override
				public void onScrollStateChanged(AbsListView view, int scrollState) {
					switch (scrollState){
					case SCROLL_STATE_IDLE:
						//靜止狀態
						//判斷最後一個元素是不是當前列表中最後一個,如果是執行分批加載動作
						break;
					case SCROLL_STATE_FLING:
						//滑翔狀態,手指脫離屏幕
						break;
					case SCROLL_STATE_TOUCH_SCROLL:
						//滾動狀態
						break;
					default:
						break;
					}
				}

雖然大多的ListView的分批加載都這麼寫,也能解決問題,但是在元素比較多的時候,滑動很快,就會出現每次加載都會停頓一下,這個看起來很不爽....


我是這麼寫的,實現 OnScrollListener 接口裏面還有一個方法 onScroll() ,只要屏幕有變化,這個方法就會被調用,在這個方法裏有三個int類型參數:

        firstVisibleItem:屏幕上顯示的第一個元素在list中的位置....

        visibleItemCount:當前屏幕上總共顯示的元素的個數

        totalItemCount:總共元素個數


思路分析:

   如果需要顯示的元素總共有5000個,分批加載優化後一次加載100個....滑動的時候如果當前顯示的元素已經到第70個,就異步加載下一批元素,這樣的話至少就不會有滑到第100個停頓一下再加載顯示,當然,還有一些細節的處理我在代碼中註釋

int i = 0;
				int ntfCut = 100;
				@Override
				public void onScroll(AbsListView view, int firstVisibleItem,
						int visibleItemCount, int totalItemCount) {
					loadList(firstVisibleItem, totalItemCount);
					//記錄前一個狀態時屏幕上第一個顯示的元素位置,用戶判斷是向上滑還是向下滑
					i = firstVisibleItem;
				}
				
				public void loadList(int firstVisibleItem, int totalItemCount){
					//如果當前list中的元素總數大於100,並且當前已經滑到第70個
					//每次加載數據 ntfCut的值會增加100,保證同一批數據只加載一次    
					if(totalItemCount >= ntfCut && firstVisibleItem >= (ntfCut - 30)){
						//分批加載獲取更多數據
						if(firstVisibleItem > i){
							//向上滑
							ntfCut += 100;
							new Thread(){
								@Override
								public void run() {
									//從數據庫中加載數據,每次都從 當前list總數開始,加載100個   limit mList.size(),100
									//得到的是有100個元素的List,遍歷add到當前List,並刷新apater,
									for(MyNotification myNtf : mnm.getListData(mList.size())){
										ntfList.add(myNtf);
									}
									handler.sendEmptyMessage(0);
								}
							}.start();
						}
					}
				}

 注 --  

   if(totalItemCount >= ntfCut && firstVisibleItem >= (ntfCut - 30)) 

   這個地方可根據個人需求做調整,因爲我加載的數據比較簡單,滑動速度快,所以我想在看到第70個的時候就加載下一批,等滑到100的時候下一批的早就加載好了,自然就流暢多了...也不建議這個地方直接寫成等於70,測試的時候,滑動速度很快的時候,偶爾會有一兩個不會執行,所以寫個範圍,確保一定執行....

  再看下在Manager中怎麼處理加載前的判斷邏輯

 

/**
	 * 獲取粉絲通知列表<分批加載>
	 * @author Jfomt
	 * @since 2014-04-12, v4.2.0
	 * @return List<MyNotification> 
	 */
	public List<MyNotification> getListData(int cut){
		int count = MyNotification.getNotificationCount();
		if(cut != 0){
			if((count - cut) >= 100){
				ntfList = MyNotification.getListByPage(cut, 100);
			}else{
				ntfList = MyNotification.getListByPage(cut, (count - cut));
			}
		}else{
			if(count > 100){
				ntfList = MyNotification.getListByPage(0, 100);
			}else{
				ntfList = MyNotification.getListByPage(0, count);
			}
		}
		return ntfList;
	}

解釋一下上面代碼:

    cut = 0   剛打開頁面,第一次請求加載數據,請求加載100個

           |—  總數 > 100     執行分頁加載,只加載前100個

           |— 總數  <= 100  從0開始,加載 count 個

   cut != 0  滑動過程中請求的分批加載

           |— 如果總數 - 已經加載過的 >= 100,那繼續從 cut開始加載100個

           |— 反之,從cut開始,加載 count-cut 個


ok,數據庫執行代碼就不說了,給limit兩個參數,執行分批加載

用5000條數據測試無壓力...非常流暢


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章