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条数据测试无压力...非常流畅


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