首页 > 数据库开发 > Sqlite数据库分页查询(ListView分页显示数据)

Sqlite数据库分页查询(ListView分页显示数据)

今天项目中遇到个问题,之前数据量不算多的时候,ListView显示正常,但是当数据量很大得分时候,进入画面,显示数据比较慢,

而且不能放在UI线程中去拿数据,用子线程去拿把,画面出来了,但是数据要等很久才会出来,因此,这样给人的体验很不好,算不上好的设计。

因此,查了一下,关于数据库分页ListView分页。

对于ListView分页,不管是本地数据查询,还是网络数据获取,都应该是常见而且不可以忽视的一点吧。

下面介绍一下我的这个demo。

流程简述:

我在raw文件夹下面放了名称为city的数据库,里面包含全国2330个城市,以及所属省,拼音简写等信息。

首先在进入MainActivity的时候,创建数据库并读入sd卡文件中data/data/databases/city。

             然后我再开启子线程去读取前50条数据,显示在ListView中。

  当用户浏览数据,前50条不够时,他会滑动ListView以查看更多数据,此时,listview的数据源会递增,50 ,100,150,。。。。

  以50为增量不断增加.....

  这样避免了因一次性加载数据造成ANR,也给用户比较好的体验。

工程目录结构:

cls_city是城市信息类,Common是工具类,ViewHolder是ListView缓存机制帮助类,DataBaseHelper  数据库操作工具类/.....

[java] view plaincopyprint?

  1. package com.example.sqlitepagetest;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6.   
  7. import android.database.Cursor;  
  8. import android.util.Log;  
  9.   
  10. /** 
  11.  * <p> 
  12.  * </p> 
  13.  * 下午9:12:42 
  14.  *  
  15.  * @auther dalvikCoder 
  16.  */  
  17. public class cls_city {  
  18.   
  19.     public String _id = "";  
  20.     public String province = "";  
  21.     public String name = "";  
  22.   
  23.     /** 
  24.      *  
  25.      * select _id,province ,name from city order by _id limit perItemNum Offset 
  26.      * currentPage*perItemNum ;--currentPage 从零开始 
  27.      * <p> 
  28.      * 根据条目数量查询 
  29.      * </p> 
  30.      *  
  31.      * @param dbh 
  32.      * @param num 
  33.      *            num[1]-->每一页显示的条目数量 num[0]--->从第几条开始 
  34.      * @return List<cls_city> 
  35.      */  
  36.     public static List<cls_city> getCityList(DatabaseHelper dbh, int num[]) {  
  37.   
  38.         String sql = "select _id,province ,name from city order by _id limit "  
  39.                 + num[0] + "," + num[1];  
  40.   
  41.         Log.e("select city's sql --------------", sql);  
  42.         Cursor cursor = dbh.rawQuery(sql);  
  43.         List<cls_city> list = new ArrayList<cls_city>();  
  44.         cls_city cls = null;  
  45.         while (cursor.moveToNext()) {  
  46.   
  47.             cls = new cls_city();  
  48.             setClassValueBycursor(cls, cursor);  
  49.             list.add(cls);  
  50.         }  
  51.   
  52.         return list;  
  53.     }  
  54.   
  55.     /** 
  56.      * <p> 
  57.      * 利用反射机制给对象赋值 
  58.      * </p> 
  59.      * @param obj 
  60.      * @param cursor void 
  61.      */  
  62.     public static void setClassValueBycursor(Object obj, Cursor cursor) {  
  63.         int ColCount = cursor.getColumnCount();  
  64.         int i = 0;  
  65.         for (i = 0; i < ColCount; i++) {  
  66.             String ColName = cursor.getColumnName(i);  
  67.   
  68.             try {  
  69.                 Field f = obj.getClass().getField(ColName);  
  70.                 String ret = cursor.getString(i);  
  71.                 if (f == null)  
  72.                     continue;  
  73.                 if (ret == null)  
  74.                     ret = "";  
  75.                 f.set(obj, ret);  
  76.             } catch (SecurityException e) {  
  77.                 // TODO Auto-generated catch block  
  78.                 e.printStackTrace();  
  79.             } catch (NoSuchFieldException e) {  
  80.                 // TODO Auto-generated catch block  
  81.                 e.printStackTrace();  
  82.             } catch (IllegalArgumentException e) {  
  83.                 // TODO Auto-generated catch block  
  84.                 e.printStackTrace();  
  85.             } catch (IllegalAccessException e) {  
  86.                 // TODO Auto-generated catch block  
  87.                 e.printStackTrace();  
  88.             }  
  89.         }  
  90.     }  
  91. }  

 

[java] view plaincopyprint?

  1. package com.example.sqlitepagetest;  
  2.   
  3. import android.util.SparseArray;  
  4. import android.view.View;  
  5.   
  6. /** 
  7.  * <p> 
  8.  * ListView缓存的写法比较多种,下面也是其中一中, 
  9.  * </p> 
  10.  * 下午9:45:29 
  11.  *  
  12.  * @auther dalvikCoder 
  13.  */  
  14. public class ViewHolder {  
  15.     // I added a generic return type to reduce the casting noise in client code  
  16.     @SuppressWarnings("unchecked")  
  17.     public static <T extends View> T get(View view, int id) {  
  18.         SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();  
  19.         if (viewHolder == null) {  
  20.             viewHolder = new SparseArray<View>();  
  21.             view.setTag(viewHolder);  
  22.         }  
  23.         View childView = viewHolder.get(id);  
  24.         if (childView == null) {  
  25.             childView = view.findViewById(id);  
  26.             viewHolder.put(id, childView);  
  27.         }  
  28.         return (T) childView;  
  29.     }  
  30.   
  31. }  



在使用了ViewHolder之后,自定义适配器里面的代码看起来舒服多了。

[java] view plaincopyprint?

  1. <span style="font-size: 14px;"@Override  
  2.     public View getView(int position, View convertView, ViewGroup parent) {  
  3.   
  4.         if (convertView == null) {  
  5.   
  6.             convertView = inflater.inflate(R.layout.city_lv_item, null);  
  7.   
  8.         }  
  9.   
  10.         TextView cityId = ViewHolder.get(convertView, R.id.cityidtxt);  
  11.         TextView provincetxt = ViewHolder.get(convertView, R.id.provincetxt);  
  12.         TextView cityName = ViewHolder.get(convertView, R.id.nametxt);  
  13.   
  14.         cls_city city = cityList.get(position);  
  15.         cityId.setText(city._id);  
  16.         provincetxt.setText(city.province);  
  17.         cityName.setText(city.name);  
  18.   
  19.         return convertView;  
  20.     }</span>  


下面是总的MainActivity类,里面的注释比较详细,也比较简单。

当然如果有兴趣你可以给ListView添加尾部视图,比如加个状态文字或者加个加个进度条,不过像本地数据,好像用不了多少时间

从数据库拿出来把,加了反而感觉多余,我性子比较急,反正我是受不了的。

 

[java] view plaincopyprint?

  1. <span style="font-size: 14px;">package com.example.sqlitepagetest;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.app.Activity;  
  7. import android.os.Bundle;  
  8. import android.os.Handler;  
  9. import android.os.Message;  
  10. import android.view.Menu;  
  11. import android.widget.AbsListView;  
  12. import android.widget.AbsListView.OnScrollListener;  
  13. import android.widget.ListView;  
  14.   
  15. public class MainActivity extends Activity {  
  16.   
  17.     private ListView cityListView;  
  18.     private List<cls_city> cityList;  
  19.     private CityAdapter cityAdapter;  
  20.   
  21.     private MyThread thread = null;  
  22.   
  23.     /** 
  24.      * 每页有数据条数 这个数量可以根据需要更改,而不需在程序中更改具体数值 
  25.      * **/  
  26.     private int perPageItemNum = 100;  
  27.     /** 当前是第几页 0表示第一页 **/  
  28.     private int currentPage = 0;  
  29.   
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.activity_main);  
  34.         setUpView();  
  35.   
  36.     }  
  37.   
  38.     private void setUpView() {  
  39.   
  40.         cityList = new ArrayList<cls_city>();  
  41.   
  42.         try {  
  43.             Common.loadCityDatabase(this);  
  44.         } catch (Exception e) {  
  45.             e.printStackTrace();  
  46.         }  
  47.         Common.dbh = new DatabaseHelper(this"city");  
  48.         cityListView = (ListView) findViewById(R.id.citylistview);  
  49.   
  50.         cityAdapter = new CityAdapter(this, cityList);  
  51.         cityListView.setAdapter(cityAdapter);  
  52.         cityListView.setOnScrollListener(new OnScrollListener() {  
  53.   
  54.             @Override  
  55.             public void onScrollStateChanged(AbsListView view, int scrollState) {  
  56.   
  57.                 if (view.getLastVisiblePosition() == view.getCount() - 1  
  58.                         && scrollState == OnScrollListener.SCROLL_STATE_IDLE) {  
  59.   
  60.                     if (thread != null && !thread.isInterrupted()) {  
  61.   
  62.                         thread.interrupt();  
  63.                         thread = null;  
  64.                     }  
  65.                     currentPage++;  
  66.                     cityListView.setSelection(view.getLastVisiblePosition());// 设置显示位置,这句只是让Listview停留在最后末尾的显示而已,加不加影响不大  
  67.                     thread = new MyThread();  
  68.                     thread.start();  
  69.   
  70.                 }  
  71.             }  
  72.   
  73.             @Override  
  74.             public void onScroll(AbsListView view, int firstVisibleItem,  
  75.                     int visibleItemCount, int totalItemCount) {  
  76.   
  77.             }  
  78.         });  
  79.   
  80.         if (thread == null) {  
  81.   
  82.             thread = new MyThread();  
  83.             thread.start();  
  84.         }  
  85.     }  
  86.   
  87.     @Override  
  88.     public boolean onCreateOptionsMenu(Menu menu) {  
  89.         // Inflate the menu; this adds items to the action bar if it is present.  
  90.         getMenuInflater().inflate(R.menu.main, menu);  
  91.         return true;  
  92.     }  
  93.   
  94.     class MyThread extends Thread {  
  95.   
  96.         @Override  
  97.         public void run() {  
  98.   
  99.             int num[] = new int[2];  
  100.             num[0] = currentPage * perPageItemNum;// 0*50 1*50 2*50  
  101.             num[1] = perPageItemNum;  
  102.             List<cls_city> dataList = cls_city.getCityList(Common.dbh, num);  
  103.             // try {  
  104.             // Thread.sleep(1000);  
  105.             // } catch (InterruptedException e) {  
  106.             // e.printStackTrace();  
  107.             // }  
  108.             Message msg = new Message();  
  109.             msg.what = 1;  
  110.             msg.obj = dataList;  
  111.             mHandler.sendMessage(msg);  
  112.   
  113.         }  
  114.     }  
  115.   
  116.     private Handler mHandler = new Handler() {  
  117.   
  118.         @Override  
  119.         public void handleMessage(Message msg) {  
  120.   
  121.             super.handleMessage(msg);  
  122.   
  123.             List<cls_city> dataList = (List<cls_city>) msg.obj;  
  124.   
  125.             if (!dataList.isEmpty()) {  
  126.   
  127.                 cityAdapter.refresh(dataList);  
  128.             }  
  129.         }  
  130.   
  131.     };  
  132.   
  133. }  
  134. </span>  


Common类

[java] view plaincopyprint?

  1. package com.example.sqlitepagetest;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.InputStream;  
  6.   
  7. import android.content.Context;  
  8.   
  9. /** 
  10.  * <p> 
  11.  * </p> 
  12.  * 下午9:02:19 
  13.  *  
  14.  * @auther dalvikCoder 
  15.  */  
  16. public class Common {  
  17.   
  18.     public static DatabaseHelper dbh = null;  
  19.   
  20.     public static void loadCityDatabase(Context context) throws Exception {  
  21.   
  22.         // ------------创建路径  
  23.         String path = "/data/data/" + context.getPackageName() + "/databases";  
  24.         File file = new File(path);  
  25.   
  26.         if (!file.exists()) {  
  27.   
  28.             file.mkdirs();  
  29.         }  
  30.         // --------------该路径下创建数据库文件  
  31.         File f = new File(path, "city");  
  32.         if (!f.exists()) {  
  33.   
  34.             InputStream is = context.getResources().openRawResource(R.raw.city);  
  35.   
  36.             FileOutputStream out = new FileOutputStream(path + "/city");  
  37.             byte buffer[] = new byte[2 * 1024];  
  38.             int len = 0;  
  39.             while ((len = is.read(buffer)) > 0) {  
  40.   
  41.                 out.write(buffer, 0, len);  
  42.   
  43.             }  
  44.             out.close();  
  45.             is.close();  
  46.   
  47.         }  
  48.     }  
  49.   
  50. }  

 

最后贴上效果图:

大家可以很清楚的看到加载的数据增长过程、

 


本文固定链接: http://www.devba.com/index.php/archives/5282.html | 开发吧

报歉!评论已关闭.