Sqlite 数据库分页查询(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  数据库操作工具类/.....

package com.example.sqlitepagetest;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import android.database.Cursor;
import android.util.Log;

/**
 * <p>
 * </p>
 * 下午9:12:42
 *
 * @auther dalvikCoder
 */
public class cls_city {

  public String _id = "";
  public String province = "";
  public String name = "";

  /**
   *
   * select _id,province ,name from city order by _id limit perItemNum Offset
   * currentPage*perItemNum ;--currentPage 从零开始
   * <p>
   * 根据条目数量查询
   * </p>
   *
   * @param dbh
   * @param num
   *            num[1]-->每一页显示的条目数量 num[0]--->从第几条开始
   * @return List<cls_city>
   */
  public static List<cls_city> getCityList(DatabaseHelper dbh, int num[]) {

    String sql = "select _id,province ,name from city order by _id limit "
        + num[0] + "," + num[1];

    Log.e("select city‘s sql --------------", sql);
    Cursor cursor = dbh.rawQuery(sql);
    List<cls_city> list = new ArrayList<cls_city>();
    cls_city cls = null;
    while (cursor.moveToNext()) {

      cls = new cls_city();
      setClassValueBycursor(cls, cursor);
      list.add(cls);
    }

    return list;
  }

  /**
   * <p>
   * 利用反射机制给对象赋值
   * </p>
   * @param obj
   * @param cursor void
   */
  public static void setClassValueBycursor(Object obj, Cursor cursor) {
    int ColCount = cursor.getColumnCount();
    int i = 0;
    for (i = 0; i < ColCount; i++) {
      String ColName = cursor.getColumnName(i);

      try {
        Field f = obj.getClass().getField(ColName);
        String ret = cursor.getString(i);
        if (f == null)
          continue;
        if (ret == null)
          ret = "";
        f.set(obj, ret);
      } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (NoSuchFieldException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}
package com.example.sqlitepagetest;

import android.util.SparseArray;
import android.view.View;

/**
 * <p>
 * ListView缓存的写法比较多种,下面也是其中一中,
 * </p>
 * 下午9:45:29
 *
 * @auther dalvikCoder
 */
public class ViewHolder {
  // I added a generic return type to reduce the casting noise in client code
  @SuppressWarnings("unchecked")
  public static <T extends View> T get(View view, int id) {
    SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
    if (viewHolder == null) {
      viewHolder = new SparseArray<View>();
      view.setTag(viewHolder);
    }
    View childView = viewHolder.get(id);
    if (childView == null) {
      childView = view.findViewById(id);
      viewHolder.put(id, childView);
    }
    return (T) childView;
  }

}

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

 @Override
  public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {

      convertView = inflater.inflate(R.layout.city_lv_item, null);

    }

    TextView cityId = ViewHolder.get(convertView, R.id.cityidtxt);
    TextView provincetxt = ViewHolder.get(convertView, R.id.provincetxt);
    TextView cityName = ViewHolder.get(convertView, R.id.nametxt);

    cls_city city = cityList.get(position);
    cityId.setText(city._id);
    provincetxt.setText(city.province);
    cityName.setText(city.name);

    return convertView;
  }

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

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

package com.example.sqlitepagetest;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

public class MainActivity extends Activity {

  private ListView cityListView;
  private List<cls_city> cityList;
  private CityAdapter cityAdapter;

  private MyThread thread = null;

  /**
   * 每页有数据条数 这个数量可以根据需要更改,而不需在程序中更改具体数值
   * **/
  private int perPageItemNum = 100;
  /** 当前是第几页 0表示第一页 **/
  private int currentPage = 0;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setUpView();

  }

  private void setUpView() {

    cityList = new ArrayList<cls_city>();

    try {
      Common.loadCityDatabase(this);
    } catch (Exception e) {
      e.printStackTrace();
    }
    Common.dbh = new DatabaseHelper(this, "city");
    cityListView = (ListView) findViewById(R.id.citylistview);

    cityAdapter = new CityAdapter(this, cityList);
    cityListView.setAdapter(cityAdapter);
    cityListView.setOnScrollListener(new OnScrollListener() {

      @Override
      public void onScrollStateChanged(AbsListView view, int scrollState) {

        if (view.getLastVisiblePosition() == view.getCount() - 1
            && scrollState == OnScrollListener.SCROLL_STATE_IDLE) {

          if (thread != null && !thread.isInterrupted()) {

            thread.interrupt();
            thread = null;
          }
          currentPage++;
          cityListView.setSelection(view.getLastVisiblePosition());// 设置显示位置,这句只是让Listview停留在最后末尾的显示而已,加不加影响不大
          thread = new MyThread();
          thread.start();

        }
      }

      @Override
      public void onScroll(AbsListView view, int firstVisibleItem,
          int visibleItemCount, int totalItemCount) {

      }
    });

    if (thread == null) {

      thread = new MyThread();
      thread.start();
    }
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }

  class MyThread extends Thread {

    @Override
    public void run() {

      int num[] = new int[2];
      num[0] = currentPage * perPageItemNum;// 0*50 1*50 2*50
      num[1] = perPageItemNum;
      List<cls_city> dataList = cls_city.getCityList(Common.dbh, num);
      // try {
      // Thread.sleep(1000);
      // } catch (InterruptedException e) {
      // e.printStackTrace();
      // }
      Message msg = new Message();
      msg.what = 1;
      msg.obj = dataList;
      mHandler.sendMessage(msg);

    }
  }

  private Handler mHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {

      super.handleMessage(msg);

      List<cls_city> dataList = (List<cls_city>) msg.obj;

      if (!dataList.isEmpty()) {

        cityAdapter.refresh(dataList);
      }
    }

  };

}

Common类

package com.example.sqlitepagetest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import android.content.Context;

/**
 * <p>
 * </p>
 * 下午9:02:19
 *
 * @auther dalvikCoder
 */
public class Common {

  public static DatabaseHelper dbh = null;

  public static void loadCityDatabase(Context context) throws Exception {

    // ------------创建路径
    String path = "/data/data/" + context.getPackageName() + "/databases";
    File file = new File(path);

    if (!file.exists()) {

      file.mkdirs();
    }
    // --------------该路径下创建数据库文件
    File f = new File(path, "city");
    if (!f.exists()) {

      InputStream is = context.getResources().openRawResource(R.raw.city);

      FileOutputStream out = new FileOutputStream(path + "/city");
      byte buffer[] = new byte[2 * 1024];
      int len = 0;
      while ((len = is.read(buffer)) > 0) {

        out.write(buffer, 0, len);

      }
      out.close();
      is.close();

    }
  }

}

贴上效果图:

时间: 2024-08-03 18:31:16

Sqlite 数据库分页查询(ListView分页显示数据)的相关文章

网络采集软件核心技术剖析系列(6)---将任意博主的全部博文下载到SQLite数据库中并通过Webbrower显示(将之前的内容综合到一起)

一 本系列随笔目录及本节代码下载 开发环境:VS2008 本节源码位置:https://github.com/songboriceboy/GatherAllStoreInDB 源码下载办法:安装SVN客户端(本文最后提供下载地址),然后checkout以下的地址:https://github.com/songboriceboy/GatherAllStoreInDB 系列文章提纲拟定如下: 1.如何使用C#语言获取博客园某个博主的全部随笔链接及标题:2.如何使用C#语言获得博文的内容:3.使用C#

MySQL、SqlServer、Oracle三大主流数据库分页查询 (MySQL分页不能用top,因为不支持)

一. MySQL 数据库 分页查询MySQL数据库实现分页比较简单,提供了 LIMIT函数.一般只需要直接写到sql语句后面就行了.LIMIT子 句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数,如果给出两个参数, 第一个参数指定返回的第一行在所有数据中的位置,从0开始(注意不是1),第二个参数指定最多返回行数.例如:select * from table WHERE … LIMIT 10; #返回前10行select * from table WHERE … LIMIT

Django 分页查询并返回jsons数据,中文乱码解决方法

一.引子 Django 分页查询并返回 json ,需要将返回的 queryset 序列化, demo 如下: # coding=UTF-8 import os from django.core import serializers from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.shortcuts import render from django.http import

thinkPHP5开发智慧软文遇到的分页第二页不显示数据的问题

在进行结果查询进行分页的时候,发现分页第一页数据正常,第二页没有数据,后面问题一样,这个是因为直接使用了: 如果此处使用如下语句: $lst=NewsModel::order('sendtime desc')->where('status',$val)->alias('a')->join('admin b','a.mtzid=b.id')->field('a.*,b.adminname')-> paginate(20);  在view中会出现只有第一页有数据的现象,故而需要使

Oracle 分页查询 插叙不出数据

进行分页查询时 使用了rownum关键字导致查询时查询不出数据 ,修改 给rownum字段取个别名,规避oracle关键字 select * from (select  rownum,row_.* from (select vil.*, c.audit_title, nvl(vil.update_time,'0001-01-01') update_time2, u.user_name as user_name, prop.property_name as pname, param.descrip

数据库 子查询和分页查询

在建立子查询时需要建立两个表 如何建立关联 关联需要在创建表结束之后关联, 右击需要关联的表,选择“设计”,出现设计界面(下方右图) 点击添加,然后点击表和列规范,出现“...”选项,点开进行选择 打开界面如下图,设置主键表为bumen 里的bcode 外键表为renyuan 里的bumen  进行查询,子查询,和分页查询 分页查询 根据已有信息确定需要分成几页 在建立关系后,如果添加主键之外的信息,会自动终止语句 1009不在bumen的bcode列,所以终止执行

分页查询和分页缓存查询,List&lt;Map&lt;String, Object&gt;&gt;遍历和Map遍历

分页查询 String sql = "返回所有符合条件记录的待分页SQL语句"; int start = (page - 1) * limit + 1; int end = page * limit; sql = "select * from (select fulltable.*, ROWNUM RN from (" + sql + ") fulltable where ROWNUM <= " + end + ") where

关于sql server远程访问Oracle数据库 OpenQuery查询返回多条数据的问题

在Sql Server远程访问Oracle 中的数据库表时: 远程语法通常为: select * from OpenQuery(Oracle链接服务器名称,‘查询语句’) eg: select * from OPENQUERY(QTX,'select * from student') 有些情况下只会返回student表一条数据 第一条 解决方法:数据源ODBC中 选择系统DNS 时,新建系统数据源 选择的对应驱动应该为Oracle Instant Client Dricver  这个驱动需要安装

Python连接Sqlite数据库及Django获取接收Html数据

def sqlitetest(txt,footer): cx = sqlite3.connect("D:\Python-Test\StuProject\db.sqlite3") cu = cx.cursor() #sql = '''insert into 'comment_comment'(txt,'footer') values (\"%s\",\"%s\");'''%(pymysql.escape_string(txt),pymysql.es