Android开发中SQLite数据库操作(二)

本篇接着上一篇继续学习SQLite数据库的查询操作,这里同样也是有两种实现方式,第一种是通过rawQuery()这个方法,接收一个sql语句,获取查询的结果内容,第二种方式是通过API中提供的Query()方法,根据指定参数来获取查询结果,下面分别来看一下这两种方式具体是怎样去实现的。

首先来看通过sql语句的实现方法:为了测试方便,我们新建了一个项目,但是创建数据库的表以及字段继续按照上一篇中我们的person表中的字段来创建,并且我们通过一个循环条件向我们的person表中添加了30条数据(便于观察)。我们知道第一种方式是通过去执行db.rawQuery()方法,我们进入到这个方法的底层源码中查看后会发现该方法给我们返回的是一个Cursor类型的游标对象,所以我们继续在我们的DbManager.java这个工具方法中添加一个static类型的返回值为Cursor类型的方法,将我们查询后的Cursor对象进行返回:

/**
 * 根据Sql语句查询获取Cursor结果集
 * @param db 数据库对象
 * @param sql sql语句
 * @param selectionArgs 查询条件的占位符
 * @return 查询结果
 */
public static Cursor queryDataFromDb(SQLiteDatabase db,String sql,
                                     String[] selectionArgs){
    Cursor cursor = null;
    if (db != null){
        cursor = db.rawQuery(sql,selectionArgs);
    }
    return cursor;
}

为了将数据直观的展示到我们的界面上面,我们在拿到这个Cursor类型的对象之后会将其转换为一个List集合类型的数据,首先,我们会按照数据库表中对应的字段,为person这张表创建一个与之对应的实体类对象,在这里创建了一个类Person.java,然后再创建一个工具方法,将Cursor类型的数据转成一个List<Person>的集合:

/**
 * Cursor对象转换成List集合
 * @param cursor 游标对象
 * @return 集合对象
 */
public static List<Person> transfromCursorToList(Cursor cursor){
    List<Person> list = new ArrayList<>();
    //moveToNext() 如果返回true表示下一条记录存在,否则表示游标中的数据读取完毕
    while (cursor.moveToNext()){
        //根据参数中指定的字段名称获取字段下标
        int columIndex = cursor.getColumnIndex(Constant._ID);
        //getInt(int columIndex)参数表示指定字段的下标 获取对应的int类型字段的值
        int _id = cursor.getInt(columIndex);
        String name = cursor.getString(cursor.getColumnIndex(Constant.NAME));
        int age = cursor.getInt(cursor.getColumnIndex(Constant.AGE));
        Person person = new Person(_id,name,age);
        list.add(person);
    }
    return list;
}
最后在我们拿到这个List集合之后,我们就可以很方便的去展示数据了,整个查询过程我们定义了一个方法,具体实现为:

/**
 * 根据sql语句查询表中数据
 */
private void queryData(){
    SQLiteDatabase db = helper.getWritableDatabase();
    String sql = "select * from "+Constant.TABLE_NAME;
    Cursor cursor = DbManager.queryDataFromDb(db,sql,null);
    List<Person> list = DbManager.transfromCursorToList(cursor);
    for (Person p:list){
        Log.e(TAG, "queryData: " + p.toString());
    }
    db.close();
}
接着我们来看一下通过API如何实现查询操作,这里我们调用db.query()这个方法,给我们返回的同样是一个Cursor类型的游标,这个方法里要传递多个参数,在代码中已给出每个参数的具体含义,然后再将Cursor转换成List集合即可,具体的实现方法为:

/**
 * 根据api查询表中数据
 */
private void apiQueryData(){
    SQLiteDatabase db = helper.getWritableDatabase();
    /**
     * query(String table, String[] columns, String selection,
     * String[] selectionArgs, String groupBy, String having,
     * String orderBy)
     * table 查询的表名
     * columns 查询表中的字段名称 null表示查询所有
     * selection 查询条件
     * selectionArgs 查询条件的占位符的取值
     * groupBy group by子句,分组条件
     * having having子句,筛选条件
     * orderBy orderBy子句,排序条件
     */
    Cursor cursor = db.query(Constant.TABLE_NAME, null, Constant._ID + ">?",
            new String[]{"5"}, null, null, Constant._ID + " desc");
    List<Person> list = DbManager.transfromCursorToList(cursor);
    for (Person p:list){
        Log.e(TAG, "apiQueryData: " + p.toString());
    }
    db.close();
}
其实说到这里我们的sqlite数据库的查询在我们android中的具体实现就已经说完了,通过上一篇和这一篇的结合,我们说完了增删改查四种操作,虽然说都对应着两种实现方式,一种为执行sql语句实现,一种为调用api实现,但是当我们去跟踪对应的底层源码,一步一步的查看过去,我们就会发现,这两种方式在底层的实现思路都是一样的,都是需要去执行SQL语句,只不过第二种方式把具体的sql语句又做了进一步的封装,提供api给我们调用,简化了一步操作而已,所以本质上并没有差别。

如果你要做的只是去在列表中展示数据库里面的数据,并不需要别的,那下面再来说一种简单的实现方式,我们可以不用将Cursor转换成List集合,可以使用sqlite的适配器来进行数据展示,这里用到了两个类SimpleCursorAdapter和CursorAdapter。

先来看一下SimpleCursorAdapter如何使用?我们在布局中添加一个ListView控件,然后我们再给展示的列表的每一个item创建一个布局文件item.xml,在里面添加三个TextView控件,并且给每个控件都指定一个id,具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/tv_id"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="_id"
        android:textColor="#fff"
        android:gravity="center"
        android:background="#f37400"/>
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="_id"
        android:textColor="#fff"
        android:gravity="center"
        android:background="#f37400"/>
    <TextView
        android:id="@+id/tv_age"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="_id"
        android:gravity="center"
        android:textColor="#fff"
        android:background="#f37400"/>
</LinearLayout>
然后在代码中我们可以直接实例化SimpleCursorAdapter,然后传入几个参数,具体每个参数的使用说明这里也给出了注释:

/**
 * 展示列表的数据源
 */
private void displayData(){
    SQLiteDatabase db = helper.getWritableDatabase();
    String sql = "select * from "+Constant.TABLE_NAME;
    Cursor cursor = DbManager.queryDataFromDb(db,sql,null);
    /**
     * SimpleCursorAdapter(Context context, int layout, Cursor c,
     * String[] from, int[] to, int flags)
     * context 上下文对象
     * layout 表示适配器控件中每一项item的布局id
     * c cursor数据源
     * from cursor中数据表字段的数组
     * to 表示展示字段对应值的控件资源id
     * flags 设置适配器的标记,观察者模式
     */
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,R.layout.item
            ,cursor,new String[]{Constant._ID,Constant.NAME,Constant.AGE},
            new int[]{R.id.tv_id,R.id.tv_name,R.id.tv_age},
            SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
    listview.setAdapter(adapter);
    db.close();
}
这样就完成了数据的展示,是不是很方便呢?

再来看一下通过CursorAdapter是如何实现的?这里需要注意CursorAdapter是一个抽象类,这也就意味着我们不能够直接拿过来使用,这里我们需要自己手动创建一个类去继承这个抽象类,然后实现其中的方法即可,我在这里创建了一个MyCursorAdapter.java的类,这里给出代码:

package com.jarchie.sqliteproject.adapter;

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.jarchie.sqliteproject.R;
import com.jarchie.sqliteproject.db.Constant;

/**
 * Created by Jarchie on 17/1/8.
 * 创建CursorAdapter适配器适配数据库中的数据
 */

public class MyCursorAdapter extends CursorAdapter {

    public MyCursorAdapter(Context context, Cursor c, int flags) {
        super(context, c, flags);
    }

    /**
     * 创建适配器控件中每个item对应的view对象
     * @param context 上下文
     * @param cursor 数据源cursor对象
     * @param viewGroup 当前item的父布局
     * @return 每项item的view对象
     */
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
        View view = LayoutInflater.from(context).inflate(R.layout.item,null);
        return view;
    }

    /**
     * 对布局中的控件进行填充
     * @param view 由newView()进行返回的每个view对象
     * @param context 上下文
     * @param cursor 数据源cursor对象
     */
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView id = (TextView) view.findViewById(R.id.tv_id);
        TextView name = (TextView) view.findViewById(R.id.tv_name);
        TextView age = (TextView) view.findViewById(R.id.tv_age);
        id.setText(cursor.getInt(cursor.getColumnIndex(Constant._ID))+"");
        name.setText(cursor.getString(cursor.getColumnIndex(Constant.NAME)));
        age.setText(cursor.getInt(cursor.getColumnIndex(Constant.AGE))+"");
    }
    
}
然后在代码中我们通过实例化我们自己的MyCursorAdapter对象去进行数据的适配展示,具体实现为:

/**
 * 展示列表的数据源
 */
private void displayData(){
    SQLiteDatabase db = helper.getWritableDatabase();
    String sql = "select * from "+Constant.TABLE_NAME;
    Cursor cursor = DbManager.queryDataFromDb(db,sql,null);
    MyCursorAdapter adapter = new MyCursorAdapter(this,cursor,
            CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
    listview.setAdapter(adapter);
    db.close();
}
这样就完成了通过适配器去展示数据库中的数据,可以为我们省去一步转换List集合的操作。

附项目中的源码:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/create_db"
        android:layout_width="240dp"
        android:layout_height="wrap_content"
        android:text="创建数据库并且插入数据"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="14dp"
        android:background="#f37400"
        android:textColor="#fff"/>

    <Button
        android:id="@+id/query_db"
        android:layout_width="240dp"
        android:layout_height="wrap_content"
        android:text="sql查询数据"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="14dp"
        android:background="#f37400"
        android:textColor="#fff"/>

    <Button
        android:id="@+id/apiquery_db"
        android:layout_width="240dp"
        android:layout_height="wrap_content"
        android:text="api查询数据"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="14dp"
        android:background="#f37400"
        android:textColor="#fff"/>

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

DbManager.java

package com.jarchie.sqliteproject.utils;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.widget.Toast;
import com.jarchie.sqliteproject.bean.Person;
import com.jarchie.sqliteproject.db.Constant;
import com.jarchie.sqliteproject.db.MySqliteHelper;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Jarchie on 17/1/7.
 * 对数据库操作的工具类,降低代码的耦合度
 */

public class DbManager {
    /**
     * 采用单例模式构建helper对象
     */
    private static MySqliteHelper helper;
    public static MySqliteHelper getInstance(Context context){
        if (helper == null){
            helper = new MySqliteHelper(context);
        }
        return helper;
    }

    /**
     * 根据sql语句在数据库中执行语句
     * @param db 数据库对象
     * @param sql sql语句
     */
    public static void execSql(SQLiteDatabase db,String sql){
        if (db != null){
            if (!TextUtils.isEmpty(sql)){
                db.execSQL(sql);
            }
        }
    }

    /**
     * 根据Sql语句查询获取Cursor结果集
     * @param db 数据库对象
     * @param sql sql语句
     * @param selectionArgs 查询条件的占位符
     * @return 查询结果
     */
    public static Cursor queryDataFromDb(SQLiteDatabase db,String sql,String[] selectionArgs){
        Cursor cursor = null;
        if (db != null){
            cursor = db.rawQuery(sql,selectionArgs);
        }
        return cursor;
    }

    /**
     * Cursor对象转换成List集合
     * @param cursor 游标对象
     * @return 集合对象
     */
    public static List<Person> transfromCursorToList(Cursor cursor){
        List<Person> list = new ArrayList<>();
        //moveToNext() 如果返回true表示下一条记录存在,否则表示游标中的数据读取完毕
        while (cursor.moveToNext()){
            //根据参数中指定的字段名称获取字段下标
            int columIndex = cursor.getColumnIndex(Constant._ID);
            //getInt(int columIndex)参数表示指定字段的下标 获取对应的int类型字段的值
            int _id = cursor.getInt(columIndex);
            String name = cursor.getString(cursor.getColumnIndex(Constant.NAME));
            int age = cursor.getInt(cursor.getColumnIndex(Constant.AGE));
            Person person = new Person(_id,name,age);
            list.add(person);
        }
        return list;
    }

}
MainActivity.java

package com.jarchie.sqliteproject;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.ListView;
import com.jarchie.sqliteproject.adapter.MyCursorAdapter;
import com.jarchie.sqliteproject.bean.Person;
import com.jarchie.sqliteproject.db.Constant;
import com.jarchie.sqliteproject.db.MySqliteHelper;
import com.jarchie.sqliteproject.utils.DbManager;
import java.util.List;

public class MainActivity extends Activity implements View.OnClickListener{
    private static final String TAG = "MainActivity";
    private MySqliteHelper helper;
    private Button createdbBtn,queryBtn,apiqueryBtn;
    private ListView listview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        helper = DbManager.getInstance(this);
        initView();
        initWidgetListener();
        displayData();
    }

    /**
     * 初始化监听事件
     */
    private void initWidgetListener() {
        createdbBtn.setOnClickListener(this);
        queryBtn.setOnClickListener(this);
        apiqueryBtn.setOnClickListener(this);
    }

    /**
     * 初始化控件
     */
    private void initView() {
        createdbBtn = (Button) findViewById(R.id.create_db);
        queryBtn = (Button) findViewById(R.id.query_db);
        apiqueryBtn = (Button) findViewById(R.id.apiquery_db);
        listview = (ListView) findViewById(R.id.listview);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.create_db:
                insertData();
                break;
            case R.id.query_db:
                queryData();
                break;
            case R.id.apiquery_db:
                apiQueryData();
                break;
        }
    }

    /**
     * 展示列表的数据源
     */
    private void displayData(){
        SQLiteDatabase db = helper.getWritableDatabase();
        String sql = "select * from "+Constant.TABLE_NAME;
        Cursor cursor = DbManager.queryDataFromDb(db,sql,null);
        /**
         * SimpleCursorAdapter(Context context, int layout, Cursor c,
         * String[] from, int[] to, int flags)
         * context 上下文对象
         * layout 表示适配器控件中每一项item的布局id
         * c cursor数据源
         * from cursor中数据表字段的数组
         * to 表示展示字段对应值的控件资源id
         * flags 设置适配器的标记
         */
//        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,R.layout.item
//                ,cursor,new String[]{Constant._ID,Constant.NAME,Constant.AGE},
//                new int[]{R.id.tv_id,R.id.tv_name,R.id.tv_age},
//                SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        MyCursorAdapter adapter = new MyCursorAdapter(this,cursor,
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        listview.setAdapter(adapter);
        db.close();
    }

    /**
     * 根据api查询表中数据
     */
    private void apiQueryData(){
        SQLiteDatabase db = helper.getWritableDatabase();
        /**
         * query(String table, String[] columns, String selection,
         * String[] selectionArgs, String groupBy, String having,
         * String orderBy)
         * table 查询的表名
         * columns 查询表中的字段名称 null表示查询所有
         * selection 查询条件
         * selectionArgs 查询条件的占位符的取值
         * groupBy group by子句,分组条件
         * having having子句,筛选条件
         * orderBy orderBy子句,排序条件
         */
        Cursor cursor = db.query(Constant.TABLE_NAME, null, Constant._ID + ">?",
                new String[]{"5"}, null, null, Constant._ID + " desc");
        List<Person> list = DbManager.transfromCursorToList(cursor);
        for (Person p:list){
            Log.e(TAG, "apiQueryData: " + p.toString());
        }
        db.close();
    }

    /**
     * 根据sql语句查询表中数据
     */
    private void queryData(){
        SQLiteDatabase db = helper.getWritableDatabase();
        String sql = "select * from "+Constant.TABLE_NAME;
        Cursor cursor = DbManager.queryDataFromDb(db,sql,null);
        List<Person> list = DbManager.transfromCursorToList(cursor);
        for (Person p:list){
            Log.e(TAG, "queryData: " + p.toString());
        }
        db.close();
    }

    /**
     * 创建数据库并且插入多条数据
     */
    private void insertData(){
        SQLiteDatabase db = helper.getWritableDatabase();
        for (int i = 1;i < 31;i++){
            String sql = "insert into "+ Constant.TABLE_NAME+" values("+i+",'Archie"+i+"',24)";
            DbManager.execSql(db,sql);
        }
        db.close();
    }

}
好了,关于android中的sqlite数据库的操作就简单的说到这里,都是一些基础的操作,希望自己能够熟练掌握吧!
发布了48 篇原创文章 · 获赞 47 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/JArchie520/article/details/54233190