Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android开发中SQLite Expert的操作技巧

$
0
0

最近学习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

这些就是数据库的高级技巧,当然了还有更多的使用技巧没有介绍出,本人能力有限嘛,还在继续学习中,如有好什么疑问,我们再继续交流,探讨技术,一起提高!

作者:Google_huchun 发表于2017/5/23 22:49:03 原文链接
阅读:655 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>