最近学习SQLite Expert,了解过后,才觉得和MySql同工异曲,深度学习android开发,就必须了解Sqlite Expert,才能更上一层楼。
在之前的一篇文章中我已经粗浅的介绍了SQLite的基本使用方法,这一骗我重点介绍一下SQlite的事务操作,适配器操作,分页操作等技巧.
当然,先简单的温习一下Sqlite基本方法,http://blog.csdn.net/google_huchun/article/details/71105034
学习SQLite ,就必须学习语法技巧,对query要有很深的理解,才能进步。
SQLiteDatabase db = SQLiteDb.getWritableDatabase();
/**
* query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
* String table 表示查询的表名
* String[] columns 表示查询表中的字段名称,null 查询所有
* String selection 表示查询条件 where子句
* String[] selectionArgs 表示查询条件占位符的取值
* String groupBy 表示分组条件 group by 子句
* String having 表示率选条件 having 子句
* String orderBy 表示排序条件 order by 子句
*/
Cursor cursor=db.query(Constant.TABLE_NAME, null, Constant._ID+">?", new String[]{"10"}, null, null, Constant._ID+" desc");
List<Person> list = DbManager.cursorToList(cursor);
for (Person p : list){
Log.i("tag", p.toString());
}
db.close();
这是query使用说明。
增删改查是SQLite的基本使用方法,认识后,再来看SQLite事务操作,用代码介绍;
SQLiteDatabase db = mHelper.getWritableDatabase();
// 开启事务
db.beginTransaction();
for (int i=1;i<=100;i++){
String sql = "replace into "+ Constant.TABLE_NAME+ " values("+i+", 'hucc"+i+"', 1822220)";
db.execSQL(sql);
}
// 设置事务标志成功,当结束事务时就会提交事务
db.setTransactionSuccessful();
// 结束事务
db.endTransaction();
db.close();
解释一下,这里使用的replace 代替了 insert 方法,因为使用insert容易引起
Android:android.database.sqlite.SQLiteConstraintException:UNIQUE constraint failed。
SQlite使用的适配器,是SimpleCursorAdapter和CursorAdapter,而Cursor游标就相当于Java中的HashMap一样,使用起来很方便。
SimpleCursorAdapter:
/**
* 将数据源数据加载到适配器中
* SimpleCursorAdapter(Context context, int list_item, Cursor c, String[] from, int[] to, int flags)
* Context context 上下文对象
* int list_item 表示适配器控件中每项item 的布局id
* Cursor c 表示Cursor 数据源
* String[] from 表示cursor 中数据表字段的数组
* int[] to 表示展示字段对应值的控件资源id
* int flags 设置适配器的标记
*/
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list_item, cursor, new String[]{Constant._ID, Constant.NAME, Constant.PHONE}, new int[]{R.id.tv_id, R.id.tv_name,R.id.tv_phone} SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
CursorAdapter:
/**
* 以内部类的定义形式适配器
*/
/**
* 表示创建适配器控件中每个item对应的view对象
* @param context 上下文
* @param cursor 数据源cursor对象
* @param parent 当前item的父布局
* @return 每项item的view对象
*/
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = LayoutInflater.from(context).inflate(R.layout.list_item,null);
return view;
}
/**
* 通过newview()方法确定了每个item展示的view对象,在bindview()对布局中的控件进行填充
* @param view 由newView()返回的每项view对象
* @param context 上下文
* @param cursor 数据源cursor对象
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tv_id = (TextView) view.findViewById(R.id.tv_id);
TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
tv_id.setText(cursor.getInt(cursor.getColumnIndex(Constant._ID))+"");
tv_name.setText(cursor.getString(cursor.getColumnIndex(Constant.NAME)));
tv_phone.setText(cursor.getInt(cursor.getColumnIndex(Constant.PHONE))+"");
}
常用的数据适配器就是以上两种,这是我根据自己的程序张贴出该模块。
当然了,也可以使用BaseAdapter操作,下来我会介绍这个适配器。
说起数据,我们使用数据就是要处理数据,根据数据才能持续开发,数据的分页操作是SQLite的重点。这里我就用ListView+BaseAdapter来介绍。
数据的分页需要自定义几类参数,
private int totalNum; //表示加载当前控件加载数据总条目
private int pageSize = 20; // 表示当前数据条目
private int pageNum; // 表示总页码
private int currentPage = 1; // 当前页码
private boolean isDivPage;
private List<Person> totalList;
在onCreate()初始化数据操作,
// 获取数据表数据总数目
totalNum = DbManager.getDataCount(db,Constant.TABLE_NAME);
// 根据总条目与每页展示数据条目,获得总页数
pageNum = (int) Math.ceil(totalNum / pageSize);
if (currentPage == 1){
totalList = DbManager.getListByCurrentPage(db,Constant.TABLE_NAME,currentPage,pageSize);
}
final MyBaseAdapter mAdapter = new MyBaseAdapter(this, totalList);
mListView.setAdapter(mAdapter);
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (isDivPage && AbsListView.OnScrollListener.SCROLL_STATE_IDLE == scrollState){
if (currentPage<pageNum){
currentPage++;
// 根据最新页码加载获取集合存储到数据源中
totalList.addAll(DbManager.getListByCurrentPage(db,Constant.TABLE_NAME, currentPage,pageSize));
mAdapter.notifyDataSetChanged();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
isDivPage = ((firstVisibleItem + visibleItemCount)==totalItemCount);
}
});
这是我事先操作了一个数据表”info.db”,添加在assets中,这样就需要打开该数据表,
private SQLiteDatabase openDatabase(Context context) {
File file = new File(DATABASE_PATH);
//查看数据库文件是否存在
if (file.exists()){
Log.i("test", "存在数据库");
// 存在则直接返回打开的数据库
return SQLiteDatabase.openOrCreateDatabase(file, null);
}else{
//不存在先创建文件夹
File path = new File(DATABASE_PATH);
Log.i("test", "pathStr="+path);
if (path.mkdir()){
Log.i("test", "创建成功");
}else{
Log.i("test", "创建失败");
}
try {
//得到资源
AssetManager am = context.getAssets();
//得到数据库的输入流
// InputStream is = am.open(Constant.DATABASE_NAME);
// InputStream is = am.open("info.db");
InputStream is = am.open(String.valueOf(R.raw.info));
Log.i("test", is+"");
//用输出流写到SDcard上面
FileOutputStream fos = new FileOutputStream(file);
Log.i("test", "fos="+fos);
Log.i("test", "file="+file);
//创建byte数组 用于1KB写一次
byte[] buffer = new byte[1024];
int count = 0;
while ((count = is.read(buffer))>0){
Log.i("test", "得到");
fos.write(buffer, 0, count);
}
fos.flush();
fos.close();
is.close();
}catch (IOException e){
e.printStackTrace();
return null;
}
}
return openDatabase(context);
}
就是代码,就是如何打开sqlite的步骤。数据的分页操作就需要根据数据表名称获取数据总条目:
/*
* id 数据库对象
* tableName 数据表名称
* 数据总条目
*/
public static int getDataCount(SQLiteDatabase db, String tableName){
int count = 0;
if (db != null){
Cursor cursor = db.rawQuery("select * from "+tableName, null);
count = cursor.getCount(); // 获取cursor中的数据总数
}
return count;
另外需要根据当前页码查询获取该页码的聚合数据.
/*
* @param db 数据库对象
* @param tableName 数据表名称
* @param currentPage 当前页码
* @return 当前页对应的集合
*
* select * from person ?,? 如何根据当前页码获取该页数据
*/
public static List<Person> getListByCurrentPage(SQLiteDatabase db, String tableName, int currentPage, int pageSize){
int index = (currentPage-1)*pageSize; // 获取当前页码第一条数据的下标
Cursor cursor = null;
if (db != null){
String sql = "select * from "+tableName+" limit ?,?";
cursor = db.rawQuery(sql, new String[]{index+"", pageSize+""});
}
return cursorToList(cursor); //将查询的cursor对象转换成list集合
}
需要更多的知识可以关注本人的代码库:
https://git.oschina.net/huchun/sqliteexpert
这些就是数据库的高级技巧,当然了还有更多的使用技巧没有介绍出,本人能力有限嘛,还在继续学习中,如有好什么疑问,我们再继续交流,探讨技术,一起提高!