http://blog.youkuaiyun.com/taki_dsm/article/details/7785042
所谓数据库的分页显示,必须先要有一个数据库,先创建一个数据库。我这里用的是继承SQLiteOpenHelper的方法。具体如下:
- package com.android.database;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.provider.BaseColumns;
- /**
- *
- * @author shangzhenxiang
- * 创建数据库,继承SQLiteOpenHelper。
- *
- */
- public class DBHelper extends SQLiteOpenHelper {
- private static final String DATABASE_NAME = "database.db";
- private static final int DATABASE_VERSION = 1;
- private static final String TABLE_NAME = "database";
- public static final String FIELD_TITLE = "title";
- public DBHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
- /**
- * 创建表,写一个创建表的sql语句,然后调用db.execSQL(sql);之后向表中添加几条数据。
- */
- @Override
- public void onCreate(SQLiteDatabase db) {
- String sql="Create table "+TABLE_NAME+"("+BaseColumns._ID+" integer primary key autoincrement,"
- + FIELD_TITLE + " text );";
- db.execSQL(sql);
- //初始化数据库
- initDatabase(db);
- }
- //向数据库的表中插入一些数据。
- private void initDatabase(SQLiteDatabase db) {
- ContentValues cv = new ContentValues();
- cv.put("title", "cctv1 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv2 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv3 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv4 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv5 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv6 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv7 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv8 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv9 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("title", "cctv10 news");
- db.insert(TABLE_NAME, null, cv);
- cv.clear();
- cv.put("news_title", "guangshui tv");
- db.insert(TABLE_NAME, null, cv);
- }
- //这里是用于更新数据库的。
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- String sql=" DROP TABLE IF EXISTS "+TABLE_NAME;
- db.execSQL(sql);
- onCreate(db);
- }
- }
package com.android.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
/**
*
* @author shangzhenxiang
* 创建数据库,继承SQLiteOpenHelper。
*
*/
public class DBHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "database.db";
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "database";
public static final String FIELD_TITLE = "title";
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* 创建表,写一个创建表的sql语句,然后调用db.execSQL(sql);之后向表中添加几条数据。
*/
@Override
public void onCreate(SQLiteDatabase db) {
String sql="Create table "+TABLE_NAME+"("+BaseColumns._ID+" integer primary key autoincrement,"
+ FIELD_TITLE + " text );";
db.execSQL(sql);
//初始化数据库
initDatabase(db);
}
//向数据库的表中插入一些数据。
private void initDatabase(SQLiteDatabase db) {
ContentValues cv = new ContentValues();
cv.put("title", "cctv1 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv2 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv3 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv4 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv5 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv6 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv7 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv8 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv9 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("title", "cctv10 news");
db.insert(TABLE_NAME, null, cv);
cv.clear();
cv.put("news_title", "guangshui tv");
db.insert(TABLE_NAME, null, cv);
}
//这里是用于更新数据库的。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String sql=" DROP TABLE IF EXISTS "+TABLE_NAME;
db.execSQL(sql);
onCreate(db);
}
}
代码注释的比较清楚,数据库很简单,只有一个id 和 title键值,id是自动增长的,是系统自动的,在创建数据库的时候,我在里面加了9跳数据,用作测试用。
数据库写完了,那好,我们要测试一下,到底生成了数据库文件没有呢?
这时我们要写一个测试程序,来生成数据库文件,这需要在 manifest文件中做一些处理,如下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.sqlite"
- android:versionCode="1"
- android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" />
- <!-- android:targetPackage 是用来存放生成的数据库的位置的,可以和manifest中的package相同 -->
- <instrumentation
- android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.sqlite"
- android:label="test for my app"/>
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <!-- 这个是用来说明android测试的包 -->
- <uses-library android:name="android.test.runner"/>
- <activity android:name=".TestSqlite"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.sqlite"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<!-- android:targetPackage 是用来存放生成的数据库的位置的,可以和manifest中的package相同 -->
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.android.sqlite"
android:label="test for my app"/>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<!-- 这个是用来说明android测试的包 -->
<uses-library android:name="android.test.runner"/>
<activity android:name=".TestSqlite"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
首先要在manifest下建一个instrumentation的东西,里面有名字,目标包:这个是存放生成的数据库文件的路径,至于标签,随便写写就可以了。
然后我们创建一个继承自AndroidTestCase得类,在里面写一个方法。
调用DBHelper里面的getReadableDatabase或者getWritableDatabase就可以生成数据库文件了,如下所示:
- package com.android.database;
- import android.test.AndroidTestCase;
- /**
- *
- * @author shangzhenxiang
- *
- */
- public class DBTest extends AndroidTestCase {
- public void testCreateRecordedDB() throws Exception {
- DBHelper recordedDbHelper = new DBHelper(this.getContext());
- /**
- * 当我们调用recordedDbHelper的getWritableDatabase()或getReadableDatabase()的时候,
- * 都会导致数据库的生成
- */
- recordedDbHelper.getWritableDatabase();
- // recordedDbHelper.getReadableDatabase();
- }
- }
package com.android.database;
import android.test.AndroidTestCase;
/**
*
* @author shangzhenxiang
*
*/
public class DBTest extends AndroidTestCase {
public void testCreateRecordedDB() throws Exception {
DBHelper recordedDbHelper = new DBHelper(this.getContext());
/**
* 当我们调用recordedDbHelper的getWritableDatabase()或getReadableDatabase()的时候,
* 都会导致数据库的生成
*/
recordedDbHelper.getWritableDatabase();
// recordedDbHelper.getReadableDatabase();
}
}
生成的数据库文件在哪里呢?
在data文件夹下的data文件夹中找到刚刚在manifest中的targetPackage:
目标包中有个database的文件夹,里面就是生成的数据库文件,如下图:
数据库完成了,我们需要写一个单独的类用来显示页数和每一页上的个数,如图所示:
- package com.android.domain;
- public class Model {
- /**
- * @author shangzhenxiang
- * index 用于显示页数
- * View_Count 用于每一页上显示的个数
- */
- private int index;
- private int View_Count;
- public Model(int index, int View_Count) {
- this.index = index;
- this.View_Count = View_Count;
- }
- public int getIndex() {
- return index;
- }
- public void setIndex(int index) {
- this.index = index;
- }
- public int getView_Count() {
- return View_Count;
- }
- public void setView_Count(int view_Count) {
- View_Count = view_Count;
- }
- }
package com.android.domain;
public class Model {
/**
* @author shangzhenxiang
* index 用于显示页数
* View_Count 用于每一页上显示的个数
*/
private int index;
private int View_Count;
public Model(int index, int View_Count) {
this.index = index;
this.View_Count = View_Count;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getView_Count() {
return View_Count;
}
public void setView_Count(int view_Count) {
View_Count = view_Count;
}
}
我们还需要一个服务来操作数据库,就是我们常说的业务逻辑层。
我们需要对数据库做什么操作,都可以写到这个类中:
- package com.android.service;
- import java.util.ArrayList;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import com.android.database.DBHelper;
- /**
- *
- * @author shangzhenxiang
- *
- */
- public class DatabaseService {
- private Context mContext;
- private DBHelper dbHelper;
- public DatabaseService(Context context) {
- // TODO Auto-generated constructor stub
- mContext = context;
- dbHelper = new DBHelper(mContext);
- }
- //添加
- public void insert(String title) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- String sql = "insert into database(title) values(?)";
- db.execSQL(sql, new String[]{title});
- }
- //删除
- public void delete(String title) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- String sql = "delete from database where title = ?";
- db.execSQL(sql, new String[]{title});
- }
- //查找
- public ArrayList<String> find(int id) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- String sql = "select * from database where _id = ? ";
- Cursor c = db.rawQuery(sql, new String[]{String.valueOf(id)});
- ArrayList<String> titles = new ArrayList<String>();
- if(c.moveToNext()) {
- String title =c.getString(c.getColumnIndexOrThrow(DBHelper.FIELD_TITLE));
- titles.add(title);
- return titles;
- }
- //不用忘记关闭Cursor。
- c.close();
- return null;
- }
- //更新
- public void upDate(int id, String title) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- String sql = "update database set title =? where _id = ?";
- db.execSQL(sql, new String[]{String.valueOf(title), String.valueOf(id)});
- }
- //查询记录的总数
- public long getCount() {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- String sql = "select count(*) from database";
- Cursor c = db.rawQuery(sql, null);
- c.moveToFirst();
- long length = c.getLong(0);
- c.close();
- return length;
- }
- /**
- * 拿到所有的记录条数
- * @param firstResult 从第几条数据开始查询。
- * @param maxResult 每页显示多少条记录。
- * @return 当前页的记录
- */
- public Cursor getAllItems(int firstResult, int maxResult) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- String sql = "select * from database limit ?,?";
- Cursor mCursor = db.rawQuery(sql, new String[]{String.valueOf(firstResult), String.valueOf(maxResult)});
- return mCursor;
- }
- }
package com.android.service;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.android.database.DBHelper;
/**
*
* @author shangzhenxiang
*
*/
public class DatabaseService {
private Context mContext;
private DBHelper dbHelper;
public DatabaseService(Context context) {
// TODO Auto-generated constructor stub
mContext = context;
dbHelper = new DBHelper(mContext);
}
//添加
public void insert(String title) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
String sql = "insert into database(title) values(?)";
db.execSQL(sql, new String[]{title});
}
//删除
public void delete(String title) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
String sql = "delete from database where title = ?";
db.execSQL(sql, new String[]{title});
}
//查找
public ArrayList<String> find(int id) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
String sql = "select * from database where _id = ? ";
Cursor c = db.rawQuery(sql, new String[]{String.valueOf(id)});
ArrayList<String> titles = new ArrayList<String>();
if(c.moveToNext()) {
String title =c.getString(c.getColumnIndexOrThrow(DBHelper.FIELD_TITLE));
titles.add(title);
return titles;
}
//不用忘记关闭Cursor。
c.close();
return null;
}
//更新
public void upDate(int id, String title) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
String sql = "update database set title =? where _id = ?";
db.execSQL(sql, new String[]{String.valueOf(title), String.valueOf(id)});
}
//查询记录的总数
public long getCount() {
SQLiteDatabase db = dbHelper.getWritableDatabase();
String sql = "select count(*) from database";
Cursor c = db.rawQuery(sql, null);
c.moveToFirst();
long length = c.getLong(0);
c.close();
return length;
}
/**
* 拿到所有的记录条数
* @param firstResult 从第几条数据开始查询。
* @param maxResult 每页显示多少条记录。
* @return 当前页的记录
*/
public Cursor getAllItems(int firstResult, int maxResult) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
String sql = "select * from database limit ?,?";
Cursor mCursor = db.rawQuery(sql, new String[]{String.valueOf(firstResult), String.valueOf(maxResult)});
return mCursor;
}
}
main.xml内有个ListView。再写一个listitem.xml布局,里面有一个ListView和2个Button:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <ListView
- android:id="@+id/testList"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="3"/>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1">
- <Button
- android:id="@+id/leftButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/previous"/>
- <Button
- android:id="@+id/rightButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/next"/>
- </LinearLayout>
- </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/testList"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="3"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1">
<Button
android:id="@+id/leftButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/previous"/>
<Button
android:id="@+id/rightButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next"/>
</LinearLayout>
</LinearLayout>
我们需要对这个ListView设置一个Adapter,如下:
- package com.android.sqlite;
- import android.content.Context;
- import android.database.Cursor;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.CursorAdapter;
- import android.widget.TextView;
- import com.android.domain.Model;
- /**
- *
- * @author shangzhenxiang
- *
- */
- public class TestListAdapter extends CursorAdapter {
- private Context mContext;
- private Cursor mCursor;
- private Model mModel;
- private LayoutInflater mInflater;
- public TestListAdapter(Context context, Cursor c, Model model) {
- super(context, c);
- System.out.println("c = " + c);
- this.mContext = context;
- this.mCursor = c;
- this.mModel = model;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(R.layout.listitem, parent, false);
- }
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- ViewHolder holder = null;
- Object tag = view.getTag();
- if(tag instanceof ViewHolder) {
- holder = (ViewHolder) view.getTag();
- }
- if(holder == null) {
- holder = new ViewHolder();
- view.setTag(holder);
- holder.title = (TextView) view.findViewById(R.id.listitemtitle);
- }
- //将从数据库中查询到的title设为ListView的Item项。
- holder.title.setText(cursor.getString(cursor.getColumnIndexOrThrow("title")));
- }
- static class ViewHolder {
- TextView title;
- }
- }
package com.android.sqlite;
import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;
import com.android.domain.Model;
/**
*
* @author shangzhenxiang
*
*/
public class TestListAdapter extends CursorAdapter {
private Context mContext;
private Cursor mCursor;
private Model mModel;
private LayoutInflater mInflater;
public TestListAdapter(Context context, Cursor c, Model model) {
super(context, c);
System.out.println("c = " + c);
this.mContext = context;
this.mCursor = c;
this.mModel = model;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.listitem, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = null;
Object tag = view.getTag();
if(tag instanceof ViewHolder) {
holder = (ViewHolder) view.getTag();
}
if(holder == null) {
holder = new ViewHolder();
view.setTag(holder);
holder.title = (TextView) view.findViewById(R.id.listitemtitle);
}
//将从数据库中查询到的title设为ListView的Item项。
holder.title.setText(cursor.getString(cursor.getColumnIndexOrThrow("title")));
}
static class ViewHolder {
TextView title;
}
}
传进去一个Model的参数和一个Cursor。Model用于显示每页的个数和第几页,Cursor用于传递数据:
在Activity中我们对Button做监听:
向左移的时候就将Model中的index减一,向右就加一,同时改变cursor中传进去的Model的值,刷新Adapter,刷新界面,
同时检查Button的可用性:
- package com.android.sqlite;
- import android.app.Activity;
- import android.database.Cursor;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ListView;
- import com.android.domain.Model;
- import com.android.service.DatabaseService;
- /**
- *
- * @author shangzhenxiang
- *
- */
- public class TestSqlite extends Activity implements OnClickListener {
- private ListView mListView;
- private TestListAdapter mTestListAdapter;
- private DatabaseService mDatabaseService;
- private Cursor mCursor;
- private Model mModel;
- private Button mLeftButton;
- private Button mRightButton;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mListView = (ListView) findViewById(R.id.testList);
- //创建一个DatabaseService的对象。
- mDatabaseService = new DatabaseService(this);
- //创建一个Model的对象,表面这是首页,并且每页显示5个Item项
- mModel = new Model(0, 5);
- //mCursor查询到的是第0页的5个数据。
- mCursor = mDatabaseService.getAllItems(mModel.getIndex()*mModel.getView_Count(), mModel.getView_Count());
- System.out.println("mCursor = " + mCursor);
- //根据参数创建一个TestListAdapter对象,并设给ListView。
- mTestListAdapter = new TestListAdapter(this, mCursor, mModel);
- mListView.setAdapter(mTestListAdapter);
- mLeftButton = (Button) findViewById(R.id.leftButton);
- mRightButton = (Button) findViewById(R.id.rightButton);
- //设置Button的监听
- mLeftButton.setOnClickListener(this);
- mRightButton.setOnClickListener(this);
- checkButton();
- }
- //在Activity 销毁的时候记得将Cursor关掉。
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- super.onDestroy();
- mCursor.close();
- }
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- int id = v.getId();
- switch (id) {
- case R.id.leftButton:
- //页数向前翻一页,同时将Cursor重新查一遍,然后changeCursor,notifyDataSetChanged。
- //检查Button的可用性。
- mModel.setIndex(mModel.getIndex() - 1);
- mCursor = mDatabaseService.getAllItems(mModel.getIndex()*mModel.getView_Count(), mModel.getView_Count());
- mTestListAdapter.changeCursor(mCursor);
- mTestListAdapter.notifyDataSetChanged();
- checkButton();
- break;
- //页数向后翻一页,同时将Cursor重新查一遍,然后changeCursor,notifyDataSetChanged。
- //检查Button的可用性。
- case R.id.rightButton:
- mModel.setIndex(mModel.getIndex() + 1);
- mCursor = mDatabaseService.getAllItems(mModel.getIndex()*mModel.getView_Count(), mModel.getView_Count());
- mTestListAdapter.changeCursor(mCursor);
- mTestListAdapter.notifyDataSetChanged();
- checkButton();
- break;
- default:
- break;
- }
- }
- /**
- * 如果页数小于或等于0,表示在第一页,向左的按钮设为不可用,向右的按钮设为可用。
- * 如果总数目减前几页的数目,得到的是当前页的数目,如果比这一页要显示的少,则说明这是最后一页,向右的按钮不可用,向左的按钮可用。
- * 如果不是以上两种情况,则说明页数在中间,两个按钮都设为可用。
- */
- private void checkButton() {
- if(mModel.getIndex() <= 0) {
- mLeftButton.setEnabled(false);
- mRightButton.setEnabled(true);
- } else if(mDatabaseService.getCount() - mModel.getIndex()*mModel.getView_Count() <= mModel.getView_Count()) {
- mRightButton.setEnabled(false);
- mLeftButton.setEnabled(true);
- } else {
- mLeftButton.setEnabled(true);
- mRightButton.setEnabled(true);
- }
- }
- }