当listview需要加载的数据过多时,若一次性载入则速度会相当缓慢,影响用户体验,这时候就需要动态加载数据,即每次载入固定长度的数据,android market的listview就是采用这种方式,使得加载看起来很平滑,响应速度很快,有助于提高用户体验。
  首先,要实现动态加载首先需要在获取数据时每次在上次获取到的数据之后的位置开始取得固定长度的数据,可通过"select * from TableName LIMIT m OFFSET n"语句实现,其中m是要取得数据的长度,n是数据的偏移量。
  然后,在Activity中需要重写listview的onScroll方法,在onScroll中添加判断条件,当上一次加载的数据显示完并滑动到底部之后需要再次获取数据,可以在UI Thread中在开启一个线程去加载数据,加载数据时应弹出一个试图提示用户正在加载。

  最后,加载数据的线程处理完毕后,刷新ListView。

  以下是实现动态加载的主要步骤:

  1. //加载数据的方法 
  2.  
  3. private void fillAdapter(int count, int begin) { 
  4.         // TODO Auto-generated method stub 
  5.         SQLiteOpenHelper mSQLiteOpenHelper = new SQLiteOpenHelper ( 
  6.                 this); 
  7.         Cursor c= mSQLiteOpenHelper .getDynamicListViewData(count, offset); 
  8.  

 

  1. //监听listview的onScroll方法 
  2.  
  3. OnScrollListener listScroll = new OnScrollListener() { 
  4.  
  5.         @Override 
  6.         public void onScrollStateChanged(AbsListView view, int scrollState) { 
  7.             // TODO Auto-generated method stub 
  8.         } 
  9.  
  10.         @Override 
  11.         public void onScroll(AbsListView view, int firstVisibleItem, 
  12.                 int visibleItemCount, int totalItemCount) { 
  13.             if(isLoading) //正在加载时就不要让在执行活动触发事件 
  14.                 return
  15.             if (firstVisibleItem + visibleItemCount == totalItemCount) { 
  16.                 // 开线程去获取数据 
  17.                 if (totalItemCount <= totalItemsCount) { 
  18.                     Integer[] params = new Integer[] { 25, currentItemCount }; 
  19.  
  20.                     mAsynchTask = new AsynchTask(); 
  21.                     mAsynchTask.execute(params); 
  22.                 } else { 
  23.                     Toast.makeText(EventTracker.this"there is no data!"
  24.                             Toast.LENGTH_SHORT).show(); 
  25.                 } 
  26.             } 
  27.         } 
  28.     }; 

 

 

  1. //通过AsyncTask更方便的实现多线程管理,使得加载效果更平滑   
  2.  
  3. private class AsynchTask extends AsyncTask<Integer, Void, Void> { 
  4.         @Override 
  5.         /**将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。 
  6.          * 这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法 
  7.          * 来更新实时的任务进度。该方法是抽象方法,子类必须实现。 */ 
  8.         protected Void doInBackground(Integer... params) { 
  9.             fillAdapter(params[0], params[1]); 
  10.             return null
  11.         } 
  12.  
  13.   @Override 
  14.         /** 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用, 
  15.          * 后台的计算结果将通过该方法传递到UI thread. 
  16.          * */ 
  17.         protected void onPreExecute() { 
  18.  
  19. //loadingView为自定义的一个dialog,用于提示用户正在加载 
  20.             mEventListView.addFooterView(loadingView); 
  21.             isLoading=true
  22.         } 
  23.  
  24.  
  25.         @Override 
  26.         /** 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用, 
  27.          * 后台的计算结果将通过该方法传递到UI thread. 
  28.          * */ 
  29.         protected void onPostExecute(Void result) {      
  30.             bindAdapter(); 
  31.             mListView.removeFooterView(loadingView); 
  32.             mListView.setSelection(currentItemCount); 
  33.             currentItemCount += 25;//每次加载25列,偏移量也递增25 
  34.             isLoading=false
  35.         } 
  36.     } 

 

  1. 数据库中方法如下: 
  2. public Cursor getDynamicListViewData(int count, int offset) { 
  3.         return getReadableDatabase().rawQuery( 
  4.                 "select * from TableName limit " + count + "offset" + offset, 
  5.                 null); 
  6.     }